2012-08-09 14 views
5

Ho qualche problema con il marshalling e non riesco a capirlo da solo. Ho cercato questo argomento, ma non avevo ancora avuto fortuna, quindi in pratica sto provando a chiamare una funzione C non gestita dalla mia applicazione C# gestita. La firma della funzione C è simile al seguente:come chiamare una funzione C da C# con un parametro WCHAR * out?

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

io non l'accesso al file DLL, so solo che la funzione è stata esposta per l'utilizzo e so che cosa si suppone la funzione di fare, ma non so cosa succede all'interno, quindi la funzione riceve un WCHAR * upn che contiene un UserPricipalName e un lungo con la lunghezza del UPN fornito. Viene anche passato un puntatore WCHAR, in cui la funzione scrive un GUID corrispondente che è associato all'UPN passato. Il puntatore guidSize fornisce la dimensione del puntatore, se è troppo piccolo il GUID scritto non è scritto completamente. Se tutto va bene la funzione dovrebbe restituire 0 (non è mai successo ancora, quando viene chiamato da C#)

ora i miei sforzi per invocare e chiamare questo sguardo funzione come questa:

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

a seguito ricevo una AccessViolationException. Ho giocato con molte varianti per chiamare la funzione, ma non sono mai riuscito a ricevere uno 0 come valore di ritorno e non sono mai riuscito a leggere il GUID come dovrei fare.

Qualsiasi aiuto con questo sarebbe apprezzato.

+0

Probabilmente è più semplice utilizzare un 'StringBuilder' nella dichiarazione della funzione P/Invoke. –

+0

@CodyGray È già un 'StringBuilder guidPtr'. 'guidPtr' è il parametro di output,' upn' è l'input. – hvd

risposta

8

Dichiarare la funzione come:

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

Chiamatela come segue:

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

Si noti che a lungo in C++ è a 32 bit, così si dovrebbe definire tutti questi casi come int nella vostra Codice C#.

+0

grazie mille ha funzionato come un fascino! : D – butterwaach

Problemi correlati