Je voudrais un exemple simple d'exportation d'une fonction à partir d'une DLL Windows C ++.
Je voudrais voir l'en-tête, le .cpp
fichier et le .def
fichier (si absolument nécessaire).
Je voudrais que le nom exporté ne soit pas décoré . Je voudrais utiliser la convention d'appel la plus standard ( __stdcall
?). Je voudrais l'utilisation __declspec(dllexport)
et ne pas avoir à utiliser de .def
fichier.
Par exemple:
//header
extern "C"
{
__declspec(dllexport) int __stdcall foo(long bar);
}
//cpp
int __stdcall foo(long bar)
{
return 0;
}
J'essaie d'éviter que l'éditeur de liens ajoute des traits de soulignement et / ou des nombres (nombre d'octets?) Au nom.
Je suis d'accord pour ne pas prendre en charge dllimport
et dllexport
utiliser le même en-tête. Je ne veux aucune information sur l'exportation des méthodes de classe C ++, juste des fonctions globales de style C.
METTRE À JOUR
Ne pas inclure la convention d'appel (et l'utilisation extern "C"
) me donne les noms d'export comme j'aime, mais qu'est-ce que cela signifie? Quelle que soit la convention d'appel par défaut, j'obtiens ce que pinvoke (.NET), declare (vb6) et GetProcAddress
j'attends? (Je suppose que GetProcAddress
cela dépendrait du pointeur de fonction créé par l'appelant).
Je veux que cette DLL soit utilisée sans fichier d'en-tête, donc je n'ai pas vraiment besoin de beaucoup de fantaisie #defines
pour rendre l'en-tête utilisable par un appelant.
Je suis d'accord avec une réponse étant que je dois utiliser un *.def
fichier.
la source
extern C
supprimera la décoration qui décrit les types de paramètres de la fonction, mais pas la décoration qui décrit la convention d'appel de la fonction; b) pour supprimer toute décoration, vous devez spécifier le nom (non décoré) dans un fichier DEF.Réponses:
Si vous voulez des exportations C simples, utilisez un projet C et non C ++. Les DLL C ++ reposent sur la gestion des noms pour tous les ismes C ++ (espaces de noms, etc.). Vous pouvez compiler votre code en C en allant dans les paramètres de votre projet sous C / C ++ -> Avancé, il existe une option "Compiler en tant que" qui correspond aux commutateurs du compilateur / TP et / TC.
Si vous souhaitez toujours utiliser C ++ pour écrire les éléments internes de votre bibliothèque, mais exporter certaines fonctions démêlées pour une utilisation en dehors de C ++, consultez la deuxième section ci-dessous.
Exportation / importation de bibliothèques DLL dans VC ++
Ce que vous voulez vraiment faire est de définir une macro conditionnelle dans un en-tête qui sera inclus dans tous les fichiers source de votre projet DLL:
Ensuite, sur une fonction que vous souhaitez exporter vous utilisez
LIBRARY_API
:Dans votre projet de construction de bibliothèque, créez une définition,
LIBRARY_EXPORTS
cela entraînera l'exportation de vos fonctions pour votre construction DLL.Puisque
LIBRARY_EXPORTS
ne sera pas défini dans un projet utilisant la DLL, lorsque ce projet inclut le fichier d'en-tête de votre bibliothèque, toutes les fonctions seront importées à la place.Si votre bibliothèque doit être multiplateforme, vous pouvez définir LIBRARY_API comme rien si vous n'êtes pas sous Windows:
Lorsque vous utilisez dllexport / dllimport, vous n'avez pas besoin d'utiliser des fichiers DEF, si vous utilisez des fichiers DEF, vous n'avez pas besoin d'utiliser dllexport / dllimport. Les deux méthodes accomplissent la même tâche de différentes manières, je crois que dllexport / dllimport est la méthode recommandée parmi les deux.
Exportation de fonctions démêlées à partir d'une DLL C ++ pour LoadLibrary / PInvoke
Si vous en avez besoin pour utiliser LoadLibrary et GetProcAddress, ou peut-être pour importer à partir d'un autre langage (par exemple PInvoke de .NET, ou FFI en Python / R, etc.), vous pouvez utiliser en
extern "C"
ligne avec votre dllexport pour dire au compilateur C ++ de ne pas modifier les noms. Et puisque nous utilisons GetProcAddress au lieu de dllimport, nous n'avons pas besoin de faire la danse ifdef d'en haut, juste un simple dllexport:Le code:
Et voici à quoi ressemblent les exportations avec Dumpbin / exports:
Donc, ce code fonctionne bien:
la source
Pour C ++:
Je viens de faire face au même problème et je pense qu'il vaut la peine de mentionner qu'un problème survient lorsque l'on utilise à la fois
__stdcall
(ouWINAPI
) etextern "C"
:Comme vous le savez,
extern "C"
supprime la décoration afin qu'au lieu de:vous obtenez un nom de symbole non décoré:
Cependant, la
_stdcall
(= macro WINAPI, qui change la convention d'appel) décore également les noms de sorte que si nous utilisons les deux, nous obtenons:et le bénéfice de
extern "C"
est perdu car le symbole est décoré (avec _ @bytes)Ceci est particulièrement délicat si vous ciblez à la fois les plates-formes x86 et x64.
Deux solutions
Utilisez un fichier de définition. Mais cela vous oblige à conserver l'état du fichier def.
le moyen le plus simple: définissez la macro (voir msdn ):
puis incluez le pragma suivant dans le corps de la fonction:
Exemple complet:
Cela exportera la fonction non décorée pour les cibles x86 et x64 tout en préservant la
__stdcall
convention pour x86. Le__declspec(dllexport)
n'est pas obligatoire dans ce cas.la source
__FUNCTION__
macro ne fonctionne que dans les fonctions.J'ai eu exactement le même problème, ma solution était d'utiliser le fichier de définition de module (.def) au lieu de
__declspec(dllexport)
définir les exportations ( http://msdn.microsoft.com/en-us/library/d91k01sh.aspx ). Je n'ai aucune idée de pourquoi cela fonctionne, mais c'est le casla source
.def
fichier module exporte exerce ses travaux, mais au détriment d'être en mesure de fournir desextern
définitions dans le fichier d' en- tête par exemple des données dans globales auquel cas, vous devez fournir laextern
définition manuellement interne des utilisations de ces données. (Oui, il y a des moments où vous en avez besoin.) Il est préférable à la fois en général et en particulier pour le code multiplate-forme d'utiliser simplement__declspec()
avec une macro afin que vous puissiez transmettre les données normalement.__stdcall
, puis__declspec(dllexport)
ne pas enlever les décorations. Ajout de la fonction à un.def
testament cependant.Je pense que _naked peut obtenir ce que vous voulez, mais il empêche également le compilateur de générer le code de gestion de pile pour la fonction. extern "C" provoque la décoration de nom de style C. Supprimez cela et cela devrait vous débarrasser de vos _. L'éditeur de liens n'ajoute pas les traits de soulignement, le compilateur le fait. stdcall entraîne l'ajout de la taille de la pile d'arguments.
Pour plus d'informations, voir: http://en.wikipedia.org/wiki/X86_calling_conventions http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx
La plus grande question est de savoir pourquoi voulez-vous faire cela? Quel est le problème avec les noms mutilés?
la source