113 votes

Exportation de fonctions à partir d'une DLL avec dllexport

Je voudrais un exemple simple de l'exportation d'une fonction à partir d'un C++ DLL de windows.

J'aimerais voir la tête de, la rpc fichier, et le fichier def (si c'est absolument nécessaire).

Je voudrais le nom exporté pour être sans décor. Je voudrais utiliser la plupart convention d'appel standard (__stdcall?). Je voudrais utiliser __declspec(dllexport) et ne pas avoir à utiliser un fichier DEF.

Par exemple:

  //header
  extern "C"
  {
   __declspec(dllexport) int __stdcall foo(long bar);
  }

  //cpp
  int __stdcall foo(long bar)
  {
    return 0;
  }

J'essaie d'éviter l'éditeur de liens ajouté des traits de soulignement et/ou de chiffres (le nombre d'octets?) pour le nom.

Je suis OK avec le fait de ne pas soutenir dllimport et dllexport en utilisant le même en-tête. Je ne veux pas d'informations sur l'exportation de la classe C++ méthodes, juste c de style des fonctions globales.

Mise à JOUR

Pas compris la convention d'appel (et en utilisant extern "C") me donne l'exportation des noms que j'aime, mais qu'est-ce que cela signifie? Est quelle que soit la convention d'appel par défaut je suis en train d'obtenir ce pinvoke (.NET), déclare (vb6), et GetProcAddress attendre? (Je suppose que pour GetProcAddress cela dépend de la fonction de pointeur de l'appelant créé).

Je veux que cette DLL pour être utilisé sans un fichier d'en-tête, donc je n'ai pas vraiment besoin de beaucoup de fantaisie #définit l'en-tête utilisable par l'appelant.

Je suis OK avec la réponse étant que je dois utiliser un fichier DEF.

157voto

joshperry Points 17727

Si vous voulez simplement C les exportations, l'utilisation d'un projet C pas du C++. C++ Dll de s'appuyer sur le nom du modificateur pour tous le C++smsi (espaces de noms, etc...). Vous pouvez compiler votre code C en allant dans les paramètres de votre projet sous C/C++->Avancé, il y a une option "Compiler" qui cooresponds pour les commutateurs de compilateur /TP et /TC.

Exportation/Importation DLL Libs dans VC++

Ce que vous voulez vraiment faire est de définir une condition de macro dans un en-tête qui sera inclus dans tous les fichiers source de votre projet DLL:

#ifdef LIBRARY_EXPORTS
#    define LIBRARY_API __declspec(dllexport)
#else
#    define LIBRARY_API __declspec(dllimport)
#endif

Puis sur une fonction que vous voulez être exportés vous utilisez LIBRARY_API:

LIBRARY_API int GetCoolInteger();

Dans votre bibliothèque de construction du projet créer un définissent LIBRARY_EXPORTS ce sera la cause de vos fonctions d'exporter votre fichier DLL construire.

Depuis LIBRARY_EXPORTS ne sera pas dans un projet de consommer de la DLL, lorsque ce projet inclut le fichier d'en-tête de votre bibliothèque, toutes les fonctions seront importés à la place.

Si votre bibliothèque est d'être multi-plateforme, vous pouvez définir LIBRARY_API que rien lorsqu'il n'est pas sur Windows:

#ifdef _WIN32
#    ifdef LIBRARY_EXPORTS
#        define LIBRARY_API __declspec(dllexport)
#    else
#        define LIBRARY_API __declspec(dllimport)
#    endif
#elseif
#    define LIBRARY_API
#endif

Lors de l'utilisation de dllexport/dllimport vous n'avez pas besoin d'utiliser DEF fichiers, si vous utilisez DEF fichiers que vous n'avez pas besoin d'utiliser dllexport/dllimport. Les deux méthodes d'accomplir la même tâche de différentes manières, je crois que dllexport/dllimport est la méthode recommandée.

L'exportation de unmangled les fonctions d'une DLL C++ pour LoadLibrary/PInvoke

Si vous avez besoin d'utiliser la fonction LoadLibrary et GetProcAddress, ou peut-être faire PInvoke .NET, vous pouvez utiliser extern "C" en ligne avec votre dllexport. Et puisque nous sommes à l'aide de GetProcAddress au lieu de dllimport nous n'avons pas besoin de faire la ifdef de danse à partir de ci-dessus, juste un simple dllexport:

Le Code:

#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)

EXTERN_DLL_EXPORT int getEngineVersion() {
  return 1;
}

EXTERN_DLL_EXPORT void registerPlugin(Kernel &K) {
  K.getGraphicsServer().addGraphicsDriver(
    auto_ptr<GraphicsServer::GraphicsDriver>(new OpenGLGraphicsDriver())
  );
}

Et voici ce que les exportations ressemble avec Dumpbin /exportations de:

  Dump of file opengl_plugin.dll

  File Type: DLL

  Section contains the following exports for opengl_plugin.dll

    00000000 characteristics
    49866068 time date stamp Sun Feb 01 19:54:32 2009
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 0001110E getEngineVersion = @ILT+265(_getEngineVersion)
          2    1 00011028 registerPlugin = @ILT+35(_registerPlugin)

Donc, ce code fonctionne:

m_hDLL = ::LoadLibrary(T"opengl_plugin.dll");

m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(
  ::GetProcAddress(m_hDLL, "getEngineVersion")
);
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(
  ::GetProcAddress(m_hDLL, "registerPlugin")
);

3voto

Rytis I Points 338

J'ai eu exactement le même problème, ma solution a été d'utiliser un fichier de définition de module (.def) au lieu de __declspec(dllexport) pour définir les exportations ( http://msdn.microsoft.com/en-us/library/d91k01sh. aspx ). Je ne sais pas pourquoi ça marche, mais ça marche

-1voto

Rob K Points 3453

Je pense que _naked pourrait obtenir ce que vous voulez, mais il empêche également le compilateur de générer de la gestion de la pile de code pour la fonction. extern "C" causes C le nom du style de décoration. Supprimer cela et qui devrait se débarrasser de votre _'. L'éditeur de liens ne pas ajouter le souligne, le compilateur ne. stdcall provoque l'argument de la taille de la pile pour être annexé.

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 pourquoi voulez-vous faire? Quel est le problème avec les noms déformés?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X