2012-08-09 8 views
5

Ich habe ein bisschen Probleme mit dem Marshalling und ich kann es einfach nicht selbst herausfinden. Ich habe nach diesem Thema gesucht, hatte aber noch kein Glück, also versuche ich eine unmanaged C-Funktion aus meiner verwalteten C# -Anwendung aufzurufen. Die Signatur der C-Funktion sieht wie folgt aus:Wie ruft man eine C-Funktion von C# mit einem WCHAR * out-Parameter auf?

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

ich keinen Zugriff auf die DLL-Datei, ich weiß nur, dass die Funktion für den Gebrauch ausgesetzt ist, und ich weiß, was die Funktion tun soll, aber ich weiß nicht, was im Inneren passiert, also empfängt die Funktion einen WCHAR * upn, der einen UserPriccalName und einen Long mit der Länge des gelieferten UPN hält. Es wird auch ein WCHAR-Zeiger übergeben, wobei die Funktion eine entsprechende GUID zurückschreibt, die dem übergebenen UPN zugeordnet ist. Der guidSize-Zeiger liefert die Größe des Zeigers, wenn er zu klein ist, wird die geschriebene GUID nicht vollständig geschrieben. Wenn alles gut geht in Ordnung sollte die Funktion 0 zurück (es noch nie passiert, wenn man von C# genannt)

Nun meine Anstrengungen aufzurufen und diese Funktion sieht wie folgt zu nennen:

[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); 

als Folge ich eine erhalten AccessViolationException. Ich habe mit vielen Varianten rumgespielt, um die Funktion aufzurufen, aber ich habe es nie geschafft, eine 0 als Rückgabewert zu erhalten, und ich konnte die GUID nie so lesen, wie ich es eigentlich sollte.

Jede Hilfe mit diesem würde geschätzt werden.

+0

Wahrscheinlich am einfachsten zu verwenden ein 'StringBuilder' in der P/Invoke Funktionsdeklaration. –

+0

@CodyGray Es ist bereits ein 'StringBuilder guidPtr'. 'guidPtr' ist der Ausgangsparameter, 'upn' ist der Eingang. – hvd

Antwort

8

Deklarieren Sie die Funktion als:

[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); 

Nennen Sie es wie folgt:

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

Hinweis, die lange in C++ 32-bit, so dass Sie alle Fälle als int definieren sollte in Ihrem C# -Code.

+0

danke viel hat wie ein Charme gearbeitet! : D – butterwaach