2010-07-13 12 views
7

Supposons qu'il existe une méthode C++ int NativeMethod(double, double *) dans Native.dll. Ma première tentative d'appeler cette méthode de code managé a été (en supposant que je ne ai pas besoin de préciser le point d'entrée)Utilisation correcte de DllImport

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

ensuite utiliser la DLL Je l'ai fait

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

//do stuff with x 

Marshal.FreeHGlobal(x); //crash 

Je voudrais comprendre pourquoi cela se bloque ici. Ma première supposition est que c'est un problème de tas dû au fait que la DLL et mon application pourraient utiliser un CRT différent. Mais si c'était le cas, pourquoi l'appel de NativeMethod ne tomberait-il pas à la place? La méthode renvoyait un x que je pouvais extraire avec succès du double.

Je suis en mesure d'obtenir l'importation de travailler en passant la double par référence

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

Pourquoi le crash FreeHGlobal dans la première tentative, et quelle est la méthode recommandée pour passer des pointeurs vers des méthodes natives? Le mot-clé out peut fonctionner correctement cette situation, mais que se passe-t-il si j'ai besoin de Marshal une chaîne? Je ne pense pas que je peux contourner Alloch et Freeh ...

+0

Quel est le message d'erreur qu'il vous donne? – Amy

+0

Bien sûr, cela devrait être typeof (double). Mais je pense que SizeOf (typeof (InpPtr)) est toujours> = SizeOf (typeof (double)), donc cela peut fonctionner d'une certaine façon. Intéressant, qu'est-ce que "faire des choses avec x" partie? –

Répondre

5

Le problème est que la méthode prend un double* qui est un pointeur vers un double. Vous passez dans un pointeur qui pointe vers un IntPtr. Ceci est important seulement en ce qu'il y a une différence de taille entre double (8 octets) et IntPtr qui est de taille variable (4 ou 8 octets). Vous devez affecter le pointeur à un double

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

Ah, merci beaucoup .. J'ai raté la partie sur la taille spécifique à la plate-forme dans la référence msdn. – insipid

2

Je ne suis pas un expert, mais il ne devrait pas être:

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

je pourrais être mal compris votre objectif, mais il semble que vous faites plus compliquée que nécessaire. Il suffit de le passer par référence et laisser le gardiennage en dessous en prendre soin.

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

double x; 

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

+1 le plus représentatif serait d'utiliser out au lieu de ref. L'OP n'a jamais initialisé le pointeur. – JaredPar

+0

@JaredPar, c'est vrai. Je ne savais pas si le PO désirait un comportement ref ou out, mais je n'ai pas reconnu cet indice évident (le fait qu'il ne l'ait pas initialisé dans l'exemple). –

+0

Quelles sont les implications de l'utilisation de out/ref par rapport à AllocHGlobal pour obtenir la mémoire non-remaniée? Le CPG peut-il réorganiser la mémoire et modifier les références de pointeur avant que la méthode/fonction ne retourne? –