Utilizzo corretto di P / Invoke
Domanda
Devo chiamare una dll esterna da c #. Questa è la definizione dell'intestazione:
enum WatchMode {
WATCH_MODE_SYSTEM = 0,
WATCH_MODE_APPLICATION = 1 };
LONG ADS_API WDT_GetMode ( LONG i_hHandle, WatchMode * o_pWatchMode );
Ho aggiunto l'enum e la chiamata in C #:
public enum WatchMode
{
WATCH_MODE_SYSTEM = 0,
WATCH_MODE_APPLICATION = 1
}
[DllImport("AdsWatchdog.dll")]
internal static extern long WDT_GetMode(long hHandle, ref WatchMode watchmode);
Questo genera un AccessViolationException. So che la dll 'funziona' perché ho anche aggiunto una chiamata a GetHandle
che restituisce il hHandle
menzionato sopra. Ho provato a cambiare il parametro in un int
( ref int watchmode
) ma ottengo lo stesso errore. Qualcuno non sa come posso invocare la chiamata sopra?
Soluzione
Stai riscontrando una differenza di problema nella dimensione dei parametri tra C # e C ++. Nel mondo C ++ / windows LONG è un numero intero con segno a 4 byte. Nel mondo C # long è un numero intero con segno a 8 byte. Dovresti cambiare la tua firma C # per prendere un int.
ffpf ha torto nel dire che dovresti usare un IntPtr qui. Risolverà questo particolare problema su una macchina a 32 bit poiché IntPtr eseguirà il marshalling come int. Se lo esegui su una macchina a 64 bit, verrà eseguito nuovamente il marshalling come numero intero con segno a 8 byte e andrà in crash.
Altri suggerimenti
Il team di interoperabilità Managed, Native e COM ha rilasciato l'assistente di interoperabilità PInvoke su codeplex. Forse può creare la firma corretta. http://www.codeplex.com/clrinterop/Release/ProjectReleases. aspx? ReleaseId = 14120