Envelopper DLL native pour C#
J'ai écrit une DLL C++ et maintenant, j'ai besoin d'appeler une fonction native à partir d'une application gérée.
De l'export natif de la fonction s'affiche comme ceci:
extern "C" __declspec(dllexport)
bool NativeMethod(char *param1, char *param2, char *result);
Donc, à partir de C# je vais appeler cette fonction en passant par 2 entrée params, 1 sortie param et, évidemment, je vais lire le retour bool valeur.
J'ai essayé d'envelopper tout cela dans beaucoup de façons, mais toujours je reçois un PInvokeStackImbalance
exception.
La seule façon que je sais d'appel de fonction native est en appliquant CallingConvention = CallingConvention.Cdecl
).NET déclaration de fonction. Cependant, de cette façon, je ne suis pas en mesure de lire la sortie de param (c'est la chaîne vide toujours) et aussi de la valeur de retour est toujours vrai.
J'ai essayé quelque chose comme: [DllImport("Madll", point d'entrée = "NativeMethod")] public static extern Boolean NativeMethod(string param1, chaîne param2, chaîne param3); Également avec param3 ou StringBuilder ou MarshalAs(UnmanagedType.LPStr)]
Vous vous rendez compte que ce paramètre de sortie ne fonctionne pas, droite? C# chaînes sont immuable.
[DllImport("MyDll.dll", Point D'Entrée = "NativeMethod", CallingConvention = CallingConvention.Cdecl)] static extern bool NativeMethod( [MarshalAs(UnmanagedType.LPStr)]chaîne param1, [MarshalAs(UnmanagedType.LPStr)]chaîne param2, [MarshalAs(UnmanagedType.LPStr)]chaîne param3); - chk ma réponse!
OriginalL'auteur bit | 2013-02-03
Vous devez vous connecter pour publier un commentaire.
Je dois d'abord régler le prototype de ta fonction native.
Étant donné que cette fonction a un interface C, vous devez utiliser un type C pour les booléens, pas en C++, comme
bool
. Vous souhaiterez peut-être utiliser Win32 l'BOOL
type.En outre, comme c'est le cas actuellement, votre fonction est sujette à dépassements de la mémoire tampon: il est préférable d'ajouter un autre paramètre pour spécifier la taille maximale de la destination
result
tampon de chaîne.Note également que la diffusion de l' convention d'appel pour les Dll de l'exportation pure C des fonctions de l'interface (comme beaucoup de fonctions de l'API Win32) est
__stdcall
(pas__cdecl
). J'aimerais l'utiliser ainsi.Dernier, depuis les deux premiers paramètres sont entrée chaînes de caractères, vous pouvez utiliser
const
de la rendre claire et appliquer la const-correctness.Donc, je ferais le prototype de l'exportation natif de la fonction comme ceci:
Puis, sur le C#, côté, vous pouvez utiliser la suite de P/Invoke:
Noter que pour la chaîne de sortie, un
StringBuilder
est utilisé.Note également que
CharSet = CharSet.Ansi
est utilisé pour le maréchal de C#Unicode UTF-16 chaînes de caractères ANSI (payer l'attention sur le fait que la conversion est avec perte - si vous voulez un sans perte de conversion, il suffit d'utiliserwchar_t*
des cordes sur le C++ côté).J'ai fait un test avec un simple C++ DLL native:
Et il est appelé avec succès par la suite C# console le code de l'application:
Vous êtes les bienvenus.
OriginalL'auteur Mr.C64
Vous vous éviterez beaucoup de P/Invoke maux de tête si vous venez d'utiliser l'Interopérabilité COM au lieu de. Mettre de la méthode dans une interface COM et modifier la signature de suivre COM conventions:
J'ai changé char* à BSTR et bool à VARIANT_BOOL parce que ce sont les types utilisés par les COM pour les cordes et les booléens, respectivement. Aussi, toutes les méthodes COM doit retourner un HRESULT. Si vous voulez une "réelle" valeur de retour, vous devez l'ajouter à la dernière hors paramètre et il marque avec la retval attribut.
Puis ajouter une référence vers le composant COM du projet C# et vous obtiendrez une interface intuitive C# signature sans avoir à deviner la façon de faire correspondre les types C++, le C# types:
(C'est la façon dont il apparaît dans l'explorateur d'Objets.)
+1 Pour un travail sérieux entre le CLR et du code natif sur la même machine, COM est le chemin à parcourir. Mais trop si vous êtes seulement à essayer de faire appel à une chose.
OriginalL'auteur user1610015
pourquoi la note à l'aide .Net code de marshaling à l'aide de DLLImport telles que les suivantes
et puis vous pouvez appeler la fonction comme la fonction locale comme suit
vous pouvez utiliser onfront de la variable
OriginalL'auteur Saddam Abu Ghaida
Remplacer
LPStr
avecLPWStr
si vous travaillez avec de larges caractères.OriginalL'auteur PaRiMaL RaJ
Le paramètre de sortie doit être un
char *
, depuis C# les chaînes sont immuables. Vous appelez la méthode (dans un contexte dangereux) comme ceci:À moins que le paramètre de sortie n'est pas une chaîne mais un seul caractère, auquel cas il vous suffit de faire ceci:
Et vous pouvez simplement l'utiliser comme ceci:
Comment est-il maintenant?
QU'EST-CE QUE L'EXCEPTION?
Il a précisé. Lire la question.
Rien ne fonctionne. Je suis forcé d'utiliser CallingConvention=CallingConvention.Cdecl option, sinon rien ne fonctionne, cependant je n'ai jamais parvenir à la bonne valeur de retour (c'est toujours vrai).
OriginalL'auteur antonijn