2010-10-10 22 views
5

suppose une dll contient les fonctions suivantesPlatform Invoke, bool et chaîne

extern "C" __declspec(dllexport) void f(bool x) 
{ 
    //do something 
} 
extern "C" __declspec(dllexport) const char* g() 
{ 
    //do something else 
} 

Ma première approche naïve d'utiliser ces fonctions à partir de C# était comme suit:

[DllImport("MyDll.dll")] 
internal static extern void f(bool x); 
[DllImport("MyDll.dll")] 
internal static extern string g(); 

La première surprise a été que Cool booléen ne se convertit pas en booléen C# (comportement d'exécution étrange, mais aucun accident, cependant). J'ai donc dû changer bool en octet et convertir de l'un à l'autre à la main. Donc, la première question est, est-il une meilleure façon de maréchal bool (notez que ce bool, non BOOL)

La deuxième surprise est que la chaîne brute retournée par la fonction dll a été détenue par la chaîne C#, pas copié , comme je m'y attendais, et finalement le code C# libère la mémoire retournée par la DLL. J'ai découvert cela parce que le programme s'est écrasé, mais j'ai ensuite changé le type de retour en sbyte * et initialisé manuellement la chaîne avec ce pointeur qui fait déjà la copie. La deuxième question est donc la suivante: 2.1: existe-t-il un meilleur moyen d'empêcher la chaîne de stockage de posséder le pointeur. 2.2: WTF ?! Pourquoi C# fait-il cela? Je veux dire, un cas évident est lorsque la fonction dll renvoie un littéral, et C# essaie de le supprimer ...

Merci d'avance, et j'espère que mes questions ne sont pas vagues ou incompréhensibles.

Répondre

5
[DllImport("MyDll.dll")] 
internal static extern void f([MarshalAs(UnmanagedType.I1)] bool x); 
[DllImport("MyDll.dll")] 
[return: MarshalAs(UnmanagedType.LPStr)] 
internal static extern string g(); 
5

Par défaut, .NET commute automatiquement entre C++ BOOL (4 octets) et le type .NET bool. Pour le bool C++ (simple octet) le type que vous devez spécifier comment Marshal:

[DllImport("MyDll.dll")] 
internal static extern void f([MarshalAs(UnmanagedType.I1)] bool x); 
+0

@Darin: drôle est un de mes amis m'a dit exactement la même chose, et devinez quoi? Ça n'a pas marché. J'utilise .Net1.1 si c'est pertinent –

+1

Actuellement, il est supporté par 1.1. voir ici http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedtype(v=VS.71).aspx – Vinzenz

+0

@Armen il devrait fonctionner selon la documentation. –