2012-08-09 10 views
5

Tengo un problema con la clasificación y no puedo resolverlo solo. He buscado este tema, pero aún no he tenido suerte, así que básicamente estoy intentando llamar a una función C no administrada desde mi aplicación C# administrada. La firma de la función C es el siguiente:cómo llamar a una función C desde C# con un parámetro WCHAR * out?

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

no acceso al archivo .dll, sólo sé que la función está siendo expuesto para el uso y sé lo que se supone que la función de hacer, pero no sé qué está sucediendo en el interior, por lo que la función recibe un WCHAR * upn que contiene un UserPricipalName y un largo con la longitud del UPN suministrado. También se pasa un puntero WCHAR, donde la función escribe un GUID correspondiente que está asociado con el UPN pasado. El puntero guidSize proporciona el tamaño del puntero; si es demasiado pequeño, el GUID escrito no está completamente escrito. Si todo va bien la función debe devolver 0 (si nunca hubiera pasado, sin embargo, cuando se llama desde C#)

ahora mis esfuerzos para invocar y llamar a este aspecto función como esta:

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

como resultado recibo una AccessViolationException. He jugado con muchas variaciones para llamar a la función, pero nunca logré recibir un 0 como valor de retorno y nunca pude leer el GUID como se supone que debo hacer.

Cualquier ayuda con esto sería apreciada.

+0

Probablemente sea más fácil usar un 'StringBuilder' en la declaración de la función P/Invocar. –

+0

@CodyGray Ya es un 'GuidPtr de StringBuilder'. 'guidPtr' es el parámetro de salida,' upn' es la entrada. – hvd

Respuesta

8

declara la función como:

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

Llámelo como sigue:

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

Tenga en cuenta que a largo en C++ es de 32 bits, por lo que debe definir todas las instancias tales como int en su C# código.

+0

¡muchas gracias trabajado como un encanto! :RE – butterwaach

Cuestiones relacionadas