Information : Utilisation _declspec (dllimport) & _declspec(dllexport) dans le code

Traductions disponibles Traductions disponibles
Numéro d'article: 132044 - Voir les produits auxquels s'applique cet article
Agrandir tout | Réduire tout

Sommaire

Résumé

Cet article vient compléter les informations contenues dans l'article suivant dans la base de connaissances Microsoft :
107501Information : __export remplacé par __declspec dans Visual C++ 32 bits
Cet article explique les avantages et les mécanismes d'utiliser _declspec (dllimport) et _declspec(dllexport) dans votre application.

Plus d'informations

L'édition 32 bits de Visual C++ utilise _declspec (dllimport) et _declspec(dllexport) pour remplacer le mot clé __export utilisé précédemment dans les versions 16 bits de Visual C++.

Vous n'avez pas besoin d'utiliser _declspec (dllimport) pour votre code se compile correctement, mais en l'utilisant vous permettez au compilateur de générer un code de meilleure qualité. Le compilateur est capable de générer un code de meilleure qualité car il connaît exactement si une fonction existe ou non dans une DLL, de sorte que le compilateur peut produire des codes ignorer un niveau d'indirection qui serait normalement être présent dans un appel de fonction ayant dépassé la limite d'une DLL.

Avec la section EXPORTS du fichier .def appropriée, _declspec(dllexport) n'est pas nécessaire. _declspec(dllexport) a été ajoutée pour fournir un moyen simple d'exportation de fonctions à partir d'un fichier .exe ou .dll sans utiliser un fichier .def.

Le reste de cet article fournit une discussion approfondie de ces problèmes relativement bas niveau.

Le format de fichier exécutable Portable Win32 est conçu pour réduire le nombre de pages qui doivent être affectés pour corriger des importations. Pour ce faire, il place toutes les adresses d'importation pour n'importe quel programme dans un emplacement unique appelé table des adresses d'importation. Ainsi, le chargeur de modifier uniquement une ou deux pages lors de l'accès à ces importations.

À l'aide de _declspec (dllimport) pour les appels de fonction

Dans l'exemple de code suivant, supposons que func1 est une fonction qui réside dans une DLL séparée à partir du fichier .exe contenant la fonction main().

Sans _declspec (dllimport), étant donné ce code :
void main(void) {
    func1();
}
				
le compilateur génère du code qui ressemble à ceci :
call func1
				
et l'éditeur de liens convertit l'appel en quelque chose comme ceci :
call 0x4000000         ; The address of 'func1'.
				
si 'func1' existe dans une autre DLL, l'éditeur de liens ne peut pas résoudre ce cas directement car il n'a aucun moyen de savoir quel est l'adresse de 'func1'. Dans les environnements 16 bits, l'éditeur de liens ajoute cette adresse de code à une liste dans le .exe que le chargeur pourrait corriger au moment de l'exécution avec l'adresse correcte. Dans les environnements 32 bits, l'éditeur de liens génère un thunk dont il connaît l'adresse. Le thunk ressemble à ceci :
   0x40000000:    jmp DWORD PTR __imp_func1
				
__imp_func1 Voici l'adresse pour l'emplacement de func1 dans la table des adresses d'importation du fichier .exe. Toutes les adresses sont ainsi connues de l'éditeur de liens. Le chargeur a uniquement mettre à jour de la table des adresses d'importation du fichier .exe au moment du chargement pour que tout fonctionne correctement.

Par conséquent, à l'aide de _declspec (dllimport) est préférable car il est préférable si l'éditeur de liens ne génère un thunk que si elle n'a pas à. Thunks augmentent le code (sur les systèmes RISC, cela peut représenter plusieurs instructions) et peut dégrader les performances du cache. Si vous indiquez au compilateur à que la fonction se trouve dans une DLL, il peut générer un appel indirect pour vous.

Donc maintenant ce code :
__declspec(dllimport) void func1(void);

void main(void) {
    func1();
}
				
génère cette instruction :
call DWORD PTR __imp_func1
				
il ne ni thunk ni instruction jmp, de sorte que le code est plus petit et plus rapide.

En revanche, pour les appels de fonction à l'intérieur d'une DLL, vous ne voulez pas que d'avoir à utiliser un appel indirect. Vous savez déjà adresse d'une fonction. Temps et d'espace sont requises pour charger et stocker l'adresse de la fonction avant un appel indirect, si bien qu'un appel direct est toujours plus rapide et plus court. Vous souhaitez uniquement utiliser __declspec (dllimport) lors de l'appel de fonctions DLL depuis l'extérieur la DLL elle-même. N'utilisez pas __declspec (dllimport) sur des fonctions à l'intérieur d'une DLL lors de la génération de cette DLL.

À l'aide de _declspec(dllexport)

Microsoft a introduit __export dans la version 16 bits du compilateur pour permettre au compilateur de générer automatiquement les noms des exportations et de les placer dans un fichier .lib. Ce fichier .lib peut ensuite être utilisé comme un .lib statique pour établir une liaison avec une DLL.

Microsoft a ajouté __declspec (dllexport) pour continuer cette commodité. Son but est d'ajouter la directive d'exportation pour le fichier objet afin que vous n'avez pas besoin d'un fichier .def.

Cette pratique est plus apparent lorsque vous essayez d'exporter les noms de fonction C++ décorés. Il n'y a pas de spécification standard pour la décoration des noms, afin que le nom d'une fonction exportée peut changer entre les versions du compilateur. Si vous utilisez _declspec(dllexport), la recompilation de la DLL et les fichiers .exe dépendants est nécessaire uniquement pour le compte d'éventuelles modifications intervenues dans la convention d'attribution de noms.

La plupart exporter directives telles que les ordinaux, NONAME ou PRIVATE, peut être effectuée uniquement dans un fichier .def, et il n'existe aucun moyen de spécifier ces attributs sans un fichier .def. Toutefois, l'utilisation de _declspec(dllexport) parallèlement à l'aide d'un fichier .def ne provoque pas d'erreurs de génération.

Sous la forme d'une référence, parcourez le fichier d'en-tête Win32 WINBASE.H. Il contient des exemples d'utilisation de __declspec (dllexport) et __declspec (dllimport) par défaut.

À l'aide de _declspec(dllexport) et _declspec (dllimport) sur des données

Dans le cas des données, à l'aide de _declspec (dllimport) est pratique car elle permet de supprimer une couche d'indirection. Lorsque vous importez des données à partir d'une DLL, vous devez toujours passer par la table des adresses d'importation. Dans les jours Win32 avant _declspec (dllimport), cela signifiait il fallait penser à effectuer un niveau supplémentaire d'indirection lors de l'accès aux données exportées à partir de la DLL :
// project.h
#ifdef _DLL     // If accessing the data from inside the DLL
   ULONG ulDataInDll;

else            // If accessing the data from outside the DLL
   ULONG *ulDataInDll;
#endif
				
vous feriez puis exporter les données dans le fichier .def :
// project.def
LIBRARY project
EXPORTS
    ulDataInDll   CONSTANT
				
et accéder à l'extérieur de la DLL :
if (*ulDataInDll == 0L) {
   // Do stuff here
}
				
lorsque vous marquez les données en tant que __declspec (dllimport), le compilateur génère automatiquement le code d'indirection pour vous. Vous n'avez plus à vous soucier de la procédure ci-dessus. Comme nous l'avons indiqué précédemment, n'utilisez pas la déclaration de _declspec (dllimport) sur les données lors de la génération de la DLL. Les fonctions de la DLL n'utilisera pas de la table des adresses d'importation pour accéder à l'objet de données. Par conséquent, vous n'aurez pas le niveau supplémentaire d'adressage indirect.

Pour exporter les données automatiquement à partir de la DLL, utilisez cette déclaration :
__declspec(dllexport) ULONG ulDataInDLL;
				

Utilisation d'un fichier .def

Si vous choisissez d'utiliser __declspec (dllimport) en même temps qu'un fichier .def, vous devez modifier le fichier .def à utiliser DATA à la place de CONSTANT afin de réduire la probabilité qu'un codage incorrect un problème dû à un :
// project.def
LIBRARY project
EXPORTS
    ulDataInDll   DATA
				
le graphique suivant montre pourquoi :
Keyword     Emits in the import lib     Exports
CONSTANT    __imp_ulDataInDll           ulDataInDll
            __ulDataInDll

DATA        __imp_ulDataInDll           ulDataInDll
				
à l'aide de _declspec (dllimport) et CONSTANT répertorie la version __imp_ et le nom non décoré dans la bibliothèque d'importation .LIB DLL qui est créé pour permettre la liaison explicite. Utilisez _declspec (dllimport) et DATA répertorie uniquement la version __imp_ du nom.

Si vous utilisez CONSTANT, soit les constructions de code suivant pourrait être utilisé pour accéder à l'ulDataInDll :
__declspec(dllimport) ULONG ulDataInDll; /*prototype*/ 
   if (ulDataInDll == 0L)   /*sample code fragment*/ 
				
- ou -
ULONG *ulDataInDll;      /*prototype*/ 
if (*ulDataInDll == 0L)  /*sample code fragment*/ 
				
Toutefois, si vous utilisez DATA dans le fichier .def, seul le code compilé à l'aide de la définition suivante peut accéder à la variable ulDataInDll :
__declspec(dllimport) ULONG ulDataInDll;
if (ulDataInDll == 0L)   /*sample code fragment*/ 
				
à l'aide de la CONSTANT est plus risquée car si vous oubliez d'utiliser le niveau supplémentaire d'indirection, vous pouviez accéder potentiellement pointeur de la table des adresses d'importation à la variable--pas la variable elle-même. Ce type de problème peut se manifester souvent sous la forme d'une violation d'accès car la table des adresses d'importation est actuellement en lecture seule par le compilateur de Microsoft et les éditeurs de liens.

L'éditeur de liens en cours de Visual C++ émet un avertissement s'il voit CONSTANT dans le fichier .def pour tenir compte de ce cas. La seule véritable raison valable d'utiliser CONSTANT est si vous ne pouvez pas recompiler un fichier objet quelconque dans lequel le fichier d'en-tête n'a pas répertorier dllimport sur le prototype.

Références

Le Visual C++ documentation en ligne fournissent une quantité importante de documentation sur le dllexport et dllimport attributs de classe de stockage. Cela inclut «Les attributs dllexport et dllimport» et les rubriques «Using dllimport et dllexport en C++» dans le chapitre «Microsoft-Specific Modifiers» du Guide de référence du langage C++ et les rubriques «Exportation de symboles» dans le chapitre «Création de DLL pour Win32» de la référence de techniques de programmation. Pour obtenir une liste complète des rubriques connexes, rechercher la documentation en ligne pour «dllimport» ou «dllexport».

Pour plus d'informations, consultez les articles suivants dans la base de connaissances Microsoft :
90530Comment faire pour exporter des données à partir d'une DLL ou une application
107501Information : __export remplacé par __declspec dans Visual C++ 32 bits

Propriétés

Numéro d'article: 132044 - Dernière mise à jour: mardi 2 décembre 2003 - Version: 2.0
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Visual C++ 1.0 Édition Professionnelle
  • Microsoft Visual C++ 2.0 Édition Professionnelle
  • Microsoft Visual C++ 2.1
  • Microsoft Visual C++ 4.0 Édition Standard
  • Microsoft Visual C++ 5.0 Édition Entreprise
  • Microsoft Visual C++ 5.0 Édition Professionnelle
Mots-clés : 
kbmt kbcode kbcompiler kbinfo KB132044 KbMtfr
Traduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 132044
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.
Exclusion de responsabilité concernant les contenus obsolètes dans la Base de connaissances
Cet article concerne des produits pour lesquels Microsoft n'offre plus de support. Il est par conséquent fourni « en l'état » et ne sera plus mis à jour.

Envoyer des commentaires

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com