Question

Je suis bloqué sur un correctif pour une ancienne application Visual C++ 6.Dans la source DLL C++ que j'ai mise

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

ce qui entraîne l'apparition de MyNewVariable (bien non décoré) dans la table d'exportation (comme indiqué par dumpbin /exports blah.dll).Cependant, je n'arrive pas à comprendre comment déclarer la variable pour pouvoir y accéder dans un fichier source C.J'ai essayé diverses choses, notamment

_declspec(dllimport) char* MyNewVariable;

mais cela me donne juste une erreur de l'éditeur de liens :

symbole externe non résolu "__declspec(dllimport) char * MyNewVariable" (__imp_?MyNewVariable@@3PADA)

extern "C" _declspec(dllimport) char* MyNewVariable;

comme suggéré par Tony (et comme je l'ai essayé auparavant), cela donne une décoration attendue différente, mais ne l'a toujours pas supprimée :

symbole externe non résolu __imp__MyNewVariable

Comment écrire la déclaration pour que la variable DLL C++ soit accessible depuis l'application C ?


La réponse

Comme identifié par botismarius et d'autres (un grand merci à tous), j'avais besoin d'un lien avec le .lib de la DLL.Pour éviter que le nom ne soit mutilé, je devais le déclarer (dans la source C) sans décorateurs, ce qui signifie que je devais utiliser le fichier .lib.

Était-ce utile?

La solution

vous devez établir un lien avec la bibliothèque générée après la compilation de la DLL.Dans les options du linker du projet, vous devez ajouter le .lib déposer.Et oui, vous devez également déclarer la variable comme :

extern "C" { declspec(dllimport) char MyNewVariable; }

Autres conseils

extern "C" est la façon dont vous supprimez la décoration - cela devrait fonctionner pour utiliser :

extern "C" declspec(dllimport) char MaNouvelleVariable ;

ou si vous voulez un en-tête pouvant être utilisé par C++ ou C (avec le commutateur /TC)

#ifdef __cplusplus
extern "C" {
#endif
declspec(dllimport) char MyNewVariable;
#ifdef __cplusplus
}
#endif

Et bien sûr, faites un lien avec la bibliothèque d'importation générée par la dll effectuant l'exportation.

Je ne sais pas qui a downmoded botismarius, car il a raison.La raison en est que le .lib généré est la bibliothèque d'importation qui permet de déclarer facilement la variable/fonction externe avec __declspec(dllimport) et utilisez-le simplement.La bibliothèque d'importation automatise simplement les tâches nécessaires LoadLibrary() et GetProcAddress() appels.Sans cela, vous devez les appeler manuellement.

Ils ont tous les deux raison.Le fait que le message d'erreur décrit __imp_?MyNewVariable@@3PADA signifie qu'il recherche le nom décoré, donc le "C" externe est nécessaire.Cependant, la liaison avec la bibliothèque d'importation est aussi nécessaire ou vous obtiendrez simplement une erreur de lien différente.

@Graeme :Vous avez raison là-dessus aussi.Je pense que le compilateur "C" que l'OP utilise n'applique pas la norme C99, mais compile en C++, modifiant ainsi les noms.Un vrai compilateur C ne comprendrait pas la partie "C" du extern "C" mot-clé.

Dans le code source de la dll vous devriez avoir cette implémentation pour que le fichier .lib exportations le symbole:

extern "C" _declspec(dllexport) char* MyNewVariable = 0;

Le client c doit utiliser un entête avec cette déclaration afin que le code client soit importer le symbole:

extern "C" _declspec(dllimport) char* MyNewVariable;

Cet en-tête provoquera une erreur de compilation si #include est ajouté dans le code source de la DLL, il est donc généralement placé dans un en-tête d'exportation qui est utilisé uniquement pour les fonctions exportées et uniquement par les clients.

Si vous en avez besoin, vous pouvez également créer un en-tête « universel » qui peut être inclus n'importe où et qui ressemble à ceci :

#ifdef __cplusplus
extern "C" {
#endif
#ifdef dll_source_file
#define EXPORTED declspec(dllexport) 
#else
#define EXPORTED declspec(dllimport) 
#endif dll_source_file
#ifdef __cplusplus
}
#endif

EXPORTED char* MyNewVariable;

Ensuite, le code source de la DLL ressemble à ceci :

#define dll_source_code 
#include "universal_header.h"

EXPORTED char* MyNewVariable = 0;

Et le client ressemble à ceci :

#include "universal_header.h"
...
MyNewVariable = "Hello, world";

Si vous faites cela souvent, le monstre #ifdef en haut peut aller dans export_magic.h et universal_header.h devient :

#include "export_magic.h"

EXPORTED char *MyNewVariable;

Je n'ai jamais utilisé _declspec(dllimport) lorsque je programmais sous Windows.Vous devriez pouvoir simplement déclarer

extern "C" char* MyNewVariable;

et un lien vers le .libb créé lors de la compilation de la DLL.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top