8
votes

Comment configurer une fonction C ++ afin qu'elle puisse être utilisée par p / invoke?

Espérons que ceci est une question sans cervelle facile, mais cela montre mon manque d'expertise avec C ++. Je suis un programmeur C # et j'ai effectué des travaux approfondis avec P / invoke dans le passé avec les dlls C ++ / C des personnes. Cependant, cette fois, j'ai décidé d'écrire un wrapper C ++ dll (non gagné) moi-même, puis appelez ma dll d'emballage de C #.

Le problème que je suis immédiatement exécuté, c'est que je ne suis pas en mesure de définir une fonction C ++ que peut être trouvé par p / invoke. Je ne sais pas ce que la syntaxe pour cela est, mais voici ce que j'essaye jusqu'à présent: xxx

à l'origine, je l'ai tout simplement eu, mais cela n'a pas fonctionné non plus: xxx

puis sur le côté C #, j'ai: xxx

Tout compile, mais quand j'exécute ce c # p / invoquer appel, je reçois un système.EntryPointNotFoundException: impossible de trouver un point d'entrée nommé 'Testfuncun' in dll 'plugins \ testdll.dll'.

Ceci doit sûrement être quelque chose d'incroyablement simple sur l'extrémité C ++ Je ne connais tout simplement pas la syntaxe pour.


0 commentaires

6 Réponses :


1
votes

Vous devez exposer cette fonction avec extern "c" sinon le nom est mutilé.


0 commentaires

13
votes

vous voudrez utiliser extern "c" ainsi que __ declSpec (exportation) , comme: xxx

pour Détails complets, voir MSDN sur les types de marshalling .


1 commentaires

Parfait, ça l'a fait! J'avais aussi essayé d'avoir juste l'extérieur "C" dans le passé, mais cela n'a pas fonctionné. Il échoue jusqu'à ce que le _DeclSpec (Dllexport) soit ajouté.



1
votes

Le compilateur C ++ modifie les noms de vos fonctions pour intégrer des informations sur les paramètres et les types de retour. Ceci s'appelle Nom Mangling. D'autre part, le compilateur C ne mange pas vos noms de fonction.

Vous pouvez dire au compilateur C ++ de fonctionner en tant que compilateur C en utilisant extern "c" code>: p>

extern "C" __declspec(dllexport) bool TestFunc { return true; }


0 commentaires

7
votes

Extension de la réponse correcte de Reed.

Un autre problème que vous pouvez exécuter lors de l'exposition d'une fonction C ++ via Pinvoke utilise des types non valides. Pinvoke peut vraiment seulement soutenir le marshalling des types primitifs et des types de données de données / de la classe de données simples. p>

Par exemple, supposons que TestFunc ait la signature suivante p> xxx pré>

même ajoutant extern "c" et __ declSpec (dllexport) code> ne suffisez pas pour exposer la fonction C ++. Au lieu de cela, vous aurez besoin de créer une fonction d'assistance qui n'a pas exposé à des types compatibles de Pinvoke, puis appela ensuite à la fonction principale. Par exemple P>

void TestFunc(const std::string& input) { ... }

extern "C" _declspec(dllexport)  void TestFuncWrapper(char* pInput) {
  std::string input(pInput);
  TestFunc(input);
}


3 commentaires

Oui, c'est précisément ce genre de raison pour laquelle j'écris une DLL de wrapper C ++, plutôt que d'essayer d'appeler toutes les fonctions dont j'ai besoin directement. Mon objectif est de créer une interface plus simple pour p / invoke, tout en laissant toute la complexité nécessaire avec des rappels et des types complexes, etc., rester sur le côté C ++. Bons points!


@ X4000, j'ai pris exactement la même approche auparavant. Sauf au lieu d'une nouvelle DLL, je viens d'ajouter les fonctions d'emballage à la même DLL. Plus de DLL auraient été plus propres.


La DLL initiale que je suis enroulée est d'un tiers, de sorte que ce n'était pas une option pour moi. Mais vous avez raison, je pense qu'il est plus propre à bien des égards pour séparer les emballages du contenu en cours d'enveloppe lorsque cela est possible.



1
votes

faire quelque chose aime ceci: xxx

puis déclarer une fonction avec le mot clé d'exportation, par exemple une fonction C ++ xxx

devenir xxx

puis la partie amusante: accédez à votre console VS et tapez: xxx

et vous verrez le Nom mangé et ordinal de toutes vos fonctions facilement exportées, alors c'est juste une affaire d'une affaire d'épicerie


0 commentaires

0
votes

Construire tous les projets avec la plate-forme Win32 et le bit approprié (E.G. X86 ou X64) Option de construction.


0 commentaires