2010-07-13 11 views
7

Supongamos que hay un método C++ int NativeMethod(double, double *) en Native.dll. Mi primer intento de llamar a este método desde el código administrado fue (suponiendo que no necesito para especificar el punto de entrada)Uso correcto de DllImport

[DllImport("Native.dll")] 
private static extern int NativeMethod(double inD, IntPtr outD); 

A continuación, utilizar el archivo DLL que hice

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); 
NativeMethod(2.0, x); 

//do stuff with x 

Marshal.FreeHGlobal(x); //crash 

Me gustaría entender por qué esto se bloquea aquí. Mi primera suposición es que es un problema de montón debido al hecho de que el DLL y mi aplicación podrían estar usando un CRT diferente. Pero si ese fuera el caso, ¿por qué la llamada al NativeMethod no se interrumpiría? El método devolvió una x de la que pude extraer el doble con éxito.

soy capaz de obtener la importación de trabajar haciendo pasar el doble por referencia

[DllImport("Native.dll")] 
private static extern int NativeMethod(double inD, IntPtr outD); 

¿Por qué el accidente FreeHGlobal en el primer intento, y lo que es la forma recomendada para pasar punteros a métodos nativos? La palabra clave out puede funcionar bien en esta situación, pero ¿qué pasa si necesito Marshal una cadena? No creo que pueda moverse Alloch y Freeh ...

+0

¿Cuál es el mensaje de error que le da? – Amy

+0

Por supuesto, esto debería ser typeof (doble). Pero creo que SizeOf (typeof (InpPtr)) siempre es> = SizeOf (typeof (double)), por lo que puede funcionar de alguna manera. Interesante, ¿qué es "hacer cosas con x"? –

Respuesta

5

El problema es que el método tiene un double* que es un puntero a un doble. Está pasando un puntero que apunta a un IntPtr. Esto es importante solo porque hay una diferencia de tamaño entre double (8 bytes) y IntPtr que es de tamaño variable (4 u 8 bytes). Es necesario asignar el puntero a una double

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)); 
+0

Ah, muchas gracias .. Me perdí la parte sobre el tamaño específico de la plataforma en la referencia msdn. – insipid

2

No soy un experto, pero no debería ser:

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double))); 
7

que podría estar mal entendido su objetivo, pero parece que está haciendo que sea más complicado de lo necesario. Solo pásalo por referencia y deja que el grupo debajo se encargue de eso.

[DllImport("Native.dll")] 
private static extern int NativeMethod(double inD, ref double outD); 

double x; 

x = 1; 
NativeMethod(2.0, ref x); 
+0

+1 el más representativo sería usar en lugar de ref. El OP nunca inicializó el puntero. – JaredPar

+0

@JaredPar, eso es cierto. No estaba seguro de si el OP deseaba un comportamiento de ref uo out, pero no pude reconocer esa pista obvia (el hecho de que no la inicializó en el ejemplo). –

+0

¿Cuáles son las implicaciones de utilizar out/ref vs. AllocHGlobal para obtener memoria no controlada? ¿Puede el GC reorganizar la memoria y cambiar las referencias del puntero antes de que regrese el método/función? –