2010-10-19 8 views
7

Tengo una DLL de C++ no administrada a la que debo llamar desde una aplicación de C# de Windows Mobile.Pasando una cadena de C# a una DLL de C no administrada en Windows Mobile

Tengo el envoltorio C# y funciona muy bien en el escritorio. Puedo llamar a las funciones de DLL desde un programa de escritorio C# y pasar cadenas sin problemas.

Sin embargo, cuando compilo lib y wrapper para la plataforma móvil, aparece un error en las líneas DllImport que dice que no se reconoce CharSet.ANSI. Las únicas opciones que tengo permiso para escribir son CharSet.Auto y CharSet.Unicode.

El problema es que, independientemente de esta configuración, las cadenas que se reciben en las funciones C++ son cadenas de caracteres anchas, y cadenas no simples * que es lo que esperan.

Podemos utilizar wcstombs() para traducir todas las cadenas al comienzo de cada función de C++, pero preferiría no modificar el lib hasta tal punto ...

¿Hay una manera de solucionar el organizar entre C# y C que funciona con .NET Compact Framework?

+0

[Social.msdn] (http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/4aed0776-638a-4fde-ad61-e2462b39a961) dice que no :( – GSerg

Respuesta

6

No, no lo hay.

Microsoft documentation especifica que:

[...] del Marco .NET Compact sólo admite Unicode, y en consecuencia sólo incluye los CharSet.Unicode (y CharSet.Auto que es igual a Unicode) valor, y does no admite ninguna de las cláusulas de la declaración Declare . Esto significa que la propiedad ExactSpelling tampoco es compatible con .

Como resultado, si su función DLL espera una cadena ANSI, que necesita para realizar la conversión en la DLL, o convertir la cadena en una matriz de bytes utilizando el método sobrecargado GetBytes de la ASCIIEncoding class, antes de llamando a la función, ya que .NET Compact Framework siempre pasará un puntero a la cadena Unicode. [...]

La solución es:

funciones en la DLL

int MARSHALMOBILEDLL_API testString(const char* value); 
const char* MARSHALMOBILEDLL_API testReturnString(const char* value); 

Envoltura

[DllImport("marshalMobileDll.dll")] 
public static extern int testString(byte[] value); 

[DllImport("marshalMobileDll.dll")] 
public static extern System.IntPtr testReturnString(byte[] value); 

Llamar código

string s1 = "1234567"; 
int v = Wrapper.testString(Encoding.ASCII.GetBytes(s1)); 

string s2 = "abcdef"; 
IntPtr ps3 = Wrapper.testReturnString(Encoding.ASCII.GetBytes(s2)); 
string s3 = IntPtrToString(ps3); 


private string IntPtrToString(IntPtr intPtr) 
{ 
    string retVal = ""; 

    byte b = 0; 
    int i = 0; 
    while ((b = Marshal.ReadByte(intPtr, i++)) != 0) 
    { 
    retVal += Convert.ToChar(b); 
    } 
    return retVal; 
} 
+0

¡Finalmente! La conversión explícita realmente parece ser la única solución posible ... Muchas gracias, ¡funciona muy bien ahora! – matpop

2

Windows CE está muy predispuesto hacia Unicode (la mayoría de las API Win32 ni siquiera tienen equivalentes ANSI). Como tal, a CF tampoco le va bien con ANSI y necesita un poco de "ayuda" para hacerlo bien.

Se puede decir que el contador de referencias que desea pasar los datos como un solo byte, los valores nulos terminar utilizando el atributo MarshalAs (the MSDN docs muestran claramente que se apoya en el CF), algo a lo largo de estas líneas:

[DllImport("mydll.dll", SetLastError = true)] 
public static extern void Foo([MarshalAs(UnmanagedType.LPStr)]string myString); 
+0

por desgracia, MarshalAs no es compatible con Compact Framework – tato

+0

Según quién? MarshalAs ciertamente * es * compatible. Lo uso con bastante regularidad y no hago casi nada más que CF. – ctacke

+0

MSDN dice que es compatible desde 3.5 SP1 –

Cuestiones relacionadas