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: p> à l'origine, je l'ai tout simplement eu, mais cela n'a pas fonctionné non plus: p> puis sur le côté C #, j'ai: p> 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'. p> Ceci doit sûrement être quelque chose d'incroyablement simple sur l'extrémité C ++ Je ne connais tout simplement pas la syntaxe pour. P> p>
6 Réponses :
Vous devez exposer cette fonction avec extern "c" code> sinon le nom est mutilé. P>
vous voudrez utiliser pour Détails complets, voir MSDN sur les types de marshalling . P> p> extern "c" code> ainsi que
__ declSpec (exportation) code>, comme:
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é.
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; }
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> 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);
}
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.
faire quelque chose aime ceci: puis déclarer une fonction avec le mot clé d'exportation, par exemple une fonction C ++ p> devenir p> puis la partie amusante: accédez à votre console VS et tapez: p> 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 p> p>
Construire tous les projets avec la plate-forme Win32 et le bit approprié (E.G. X86 ou X64) Option de construction. P>