web-dev-qa-db-fra.com

Exportation de données statiques dans A DLL

J'ai un DLL qui contient une classe avec statique --Membres. J'utilise __declspec(dllexport) Afin de faire appel à cette classe Méthodes. Mais lorsque je le lie à un autre projet et essayez de le compiler, je reçois des erreurs "symboliques externes non résolues" pour les données statiques.

par exemple. Dans dll, test.h

class __declspec(dllexport) Test{
protected:
    static int d;
public:
    static void m(){int x = a;}
}

Dans dll, test.cpp

#include "Test.h"

int Test::d;

Dans l'application qui utilise le test, j'appelle m ().

J'ai également essayé d'utiliser __declSpec (dllexport) pour chaque méthode séparément, mais je reçois toujours les mêmes erreurs de liaison pour les membres statiques.

Si je vérifie le DLL (le .lib) à l'aide de Dumbin, je pouvais voir que les symboles ont été exportés.

Par exemple, l'application donne l'erreur suivante au moment de la liaison:

1>Main.obj : error LNK2001: unresolved external symbol "protected: static int CalcEngine::i_MatrixRow" (?i_MatrixRow@CalcEngine@@1HA)

Mais le déversement du .lib contient:

Version      : 0
  Machine      : 14C (x86)
  TimeDateStamp: 4BA3611A Fri Mar 19 17:03:46 2010
  SizeOfData   : 0000002C
  DLL name     : CalcEngine.dll
  Symbol name  : ?i_MatrixRow@CalcEngine@@1HA (protected: static int CalcEngine::i_MatrixRow)
  Type         : data
  Name type    : name
  Hint         : 31
  Name         : ?i_MatrixRow@CalcEngine@@1HA

Je ne peux pas comprendre comment résoudre ceci. Qu'est-ce que je fais mal? Comment puis-je passer sur ces erreurs?

P.s. Le code a été développé à l'origine pour Linux et la combinaison .SO/Binary Works sans problème

Edit: Dans le cas donné, les variables statiques ne sont pas directement référées par l'application, mais la méthode est inline car elle est dans l'en-tête. J'ai pu résoudre les erreurs de liaison en déplaçant les méthodes vers le fichier .cpp.

33
Gayan

Dans this thread à cprogramming.com Il est suggéré qu'une variable statique est locale à la DLL et non exportée.

Résumé de la discussion ci-dessous

Le membre statique n'est pas accédé directement par code dans l'application appelante, uniquement via des fonctions membres de la classe dans la DLL. Cependant, il y a plusieurs fonctions en ligne accéder à l'élément statique. Ces fonctions seront alignées dans le code des applications appelantes apportant l'application appelante accéder directement au membre statique. Cela violera la constatation référencée ci-dessus que les variables statiques sont locales à la DLL et ne peuvent pas être référencées à partir de l'application d'appel.

17
Anders Abel

Je suppose que la classe qui utilise le DLL doit voir dllimport au lieu de dllexport dans l'en-tête. Si je suis correct, cela peut Généralement être réalisé en définissant une macro de préprocesseur comme:

#ifdef EXPORTING
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif

puis utilisez-le dans la déclaration de classe:

class DECLSPEC Test{
protected:
    static int d;
public:
    static void m(){}
}

De sorte que dans le test.cpp (ou partout où il a du sens dans votre DLL==), vous pouvez spécifier que vous exportez de manière à être exporté avec Dllexport:

#define EXPORTING
#include "Test.h"

int Test::d;

alors que l'autre projet, qui ne définit pas l'exportation, verra Dllimport.

Est-ce que ça fait du sens?

11
Ghislain Fourny

Avec des dlls Windows, il existe une distinction spécifique entre __declspec(dllexport) vs __declspec(dllimport), dllexport _ doit être utilisé lors de la compilation de la DLL, dllimport doit être utilisé lorsque Compilation de programmes liés à cette DLL. La manière standard de définir ce serait avec une macro.

Voici l'exemple Visual Studio:

// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the DLL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// DLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
3
Ramon Zarazua B.