2012-08-09 12 views
5

Mam trochę problemów z marshalingiem i po prostu nie mogę tego rozwiązać sam. Szukałem tego tematu, ale nie miałem jeszcze szczęścia, więc w zasadzie próbuję wywołać niezarządzaną funkcję C z mojej zarządzanej aplikacji C#. Podpis funkcji C wygląda następująco:jak wywołać funkcję C z C# z parametrem WCHAR * out?

long MyFunction(WCHAR* upn, long upnSize, WCHAR* guid, long* guidSize); 

Nie mam dostępu do pliku .dll, ja po prostu wiem, że funkcja jest narażony na wykorzystanie i wiem, co funkcja ma robić, ale nie wiem, co się dzieje w środku, więc funkcja otrzymuje WCHAR * upn z UserPricipalName i long o długości dostarczonego UPN. Również wskaźnik WCHAR jest przekazywany wzdłuż, gdzie funkcja zapisuje z powrotem odpowiedni identyfikator GUID, który jest powiązany z przekazanym UPN. Wskaźnik guidSize dostarcza rozmiar wskaźnika, jeśli jest zbyt mały, zapisany identyfikator GUID nie jest w pełni zapisany. Jeśli wszystko pójdzie dobrze funkcja powinna zwrócić 0 (to nigdy nie zdarzyło się jeszcze, gdy wywołana z C#)

teraz moje wysiłki, aby przywoływać i wywołać tę funkcję wyglądać następująco:

[DllImport(@"MyDll.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
public static extern long MyFunction(IntPtr upnPtr, long upnSize, [Out, MarshalAsAttribute(UnmanagedType.LPWStr) ] StringBuilder guidPtr, IntPtr guidSizePtr); 


//my attempt to call the Dll's exposed function 
string upn = [email protected]; 
long upnSize = upn.Length; 
IntPtr upnPtr = Marshal.StringToHGlobalUni(upn); 

IntPtr guidSizePtr = Marshal.AllocHGlobal(sizeof(long)); 
Marshal.WriteInt32(GuidSizePtr, 128); 
var guidSB = new StringBuilder(128); 

result = MyFunction(upnPtr, upnSize, guidSB, guidSizePtr); 

w wyniku otrzymam AccessViolationException. Grałem z wieloma odmianami, aby wywołać funkcję, ale nigdy nie udało mi się otrzymać wartości 0 jako wartości zwracanej i nigdy nie byłem w stanie odczytać identyfikatora GUID, tak jak powinienem.

Każda pomoc w tym zakresie byłaby doceniana.

+0

Prawdopodobnie najłatwiejszy w użyciu "StringBuilder" w deklaracji funkcji P/Invoke. –

+0

@CodyGray To już 'StringBuilder guidPtr'. 'guidPtr' jest parametrem wyjściowym,' upn' jest wejściem. – hvd

Odpowiedz

8

stwierdzenie funkcji jak:

[DllImport(@"MyDll.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
    public static extern int MyFunction([MarshalAsAttribute(UnmanagedType.LPWStr)] string upnPtr, int upnSize, [MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder guidPtr, ref int guidSizePtr); 

Nazwijmy to w następujący sposób:

 string upn = "[email protected]"; 
     var guidSB = new StringBuilder(128); 
     int guidSizePtr =guidSB.Capacity; 
     MyFunction(upn, upn.Length, guidSB, ref guidSizePtr); 

Należy pamiętać, że długo w C++ to 32-bitowy, więc należy zdefiniować wszystkie takie przypadki jak int w swojej Kod C#.

+0

dziękuję bardzo działało jak czar! :RE – butterwaach

Powiązane problemy