2010-07-13 18 views
7

Supponiamo che esista un metodo C++ int NativeMethod(double, double *) in un file Native.dll. Il mio primo tentativo di chiamare questo metodo dal codice gestito è stato (supponendo non ho bisogno di specificare il punto di ingresso)Uso corretto di DllImport

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

quindi di utilizzare la DLL che ho fatto

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

//do stuff with x 

Marshal.FreeHGlobal(x); //crash 

vorrei capire perché questo si blocca qui. La mia prima ipotesi è che si tratta di un problema di heap dovuto al fatto che la DLL e la mia applicazione potrebbero utilizzare un CRT diverso. Ma se fosse il caso, perché invece la chiamata al blocco NativeMethod non sarebbe? Il metodo ha restituito una x che potrei estrarre con successo il doppio da.

io sono in grado di ottenere l'importazione di lavorare passando il doppio per riferimento

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

Perché il crollo FreeHGlobal nel primo tentativo, e qual è il metodo consigliato per passare puntatori a metodi nativi? La parola chiave out potrebbe funzionare bene questa situazione, ma cosa succede se ho bisogno di maresciallo una stringa? Io non penso di poter andare in giro Alloch e Freeh ...

+0

Qual è il messaggio di errore che ti dà? – Amy

+0

Ovviamente, questo dovrebbe essere typeof (double). Ma penso che SizeOf (typeof (InpPtr)) sia sempre> = SizeOf (typeof (double)), quindi potrebbe funzionare in qualche modo. Interessante, che cos'è la parte "fai roba con x"? –

risposta

5

Il problema è che il metodo prende un double* che è un puntatore a un doppio. Stai passando un puntatore che punta a uno IntPtr. Questo è importante solo in quanto vi è una differenza di dimensioni tra double (8 byte) e IntPtr che è di dimensioni variabili (4 o 8 byte). È necessario allocare il puntatore ad un double

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

Ah, molte grazie. Ho perso la parte relativa alla dimensione specifica della piattaforma nel riferimento msdn. – insipid

2

Io non sono un esperto, ma non dovrebbe essere:

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

potrei essere equivoco il tuo obiettivo, ma sembra si stanno facendo più complicato di quanto sia necessario. Basta passarlo per riferimento e lasciare che lo smistamento sottostante si occupi di esso.

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

double x; 

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

+1 il più rappresentativo sarebbe da utilizzare invece di rif. L'OP non ha mai inizializzato il puntatore. – JaredPar

+0

@JaredPar, è vero. Non ero sicuro che l'OP desiderasse ref o out, ma non sono riuscito a riconoscere quell'evidente indizio (il fatto che non l'abbia inizializzato nell'esempio). –

+0

Quali sono le implicazioni dell'utilizzo di out/ref vs. AllocHGlobal per ottenere una memoria non modificata? Il GC può riorganizzare la memoria e modificare i riferimenti del puntatore prima che il metodo/la funzione ritorni? –