Règles générales et limitations
Section spécifique à Microsoft
Si vous déclarez une fonction ou un objet sans l’attribut ou
dllexport
ladllimport
fonction, la fonction ou l’objet n’est pas considéré comme faisant partie de l’interface DLL. Par conséquent, la définition de la fonction ou de l'objet doit être présente dans ce module ou dans un autre module du même programme. Pour faire partie de la fonction ou de l’objet de l’interface DLL, vous devez déclarer la définition de la fonction ou de l’objet dans l’autre module en tant quedllexport
. Sinon, une erreur d'éditeur de liens est générée.Si vous déclarez une fonction ou un objet avec l’attribut
dllexport
, sa définition doit apparaître dans un module du même programme. Sinon, une erreur d'éditeur de liens est générée.Si un seul module de votre programme contient à la fois
dllimport
etdllexport
des déclarations pour la même fonction ou le même objet, l’attributdllexport
est prioritaire sur l’attributdllimport
. Toutefois, un avertissement du compilateur est généré. Par exemple :__declspec( dllimport ) int i; __declspec( dllexport ) int i; // Warning; inconsistent; // dllexport takes precedence.
En C++, vous pouvez initialiser un pointeur de données local global déclaré ou statique ou avec l’adresse d’un objet de données déclaré avec l’attribut
dllimport
, ce qui génère une erreur en C. En outre, vous pouvez initialiser un pointeur de fonction local statique avec l’adresse d’une fonction déclarée avec l’attributdllimport
. En C, ce type d'assignation définit le pointeur sur l'adresse de la conversion de code d'importation de la DLL (stub de code qui transfère un contrôle à la fonction) plutôt que l'adresse de la fonction. En C++, il définit le pointeur sur l'adresse de la fonction. Par exemple :__declspec( dllimport ) void func1( void ); __declspec( dllimport ) int i; int *pi = &i; // Error in C static void ( *pf )( void ) = &func1; // Address of thunk in C, // function in C++ void func2() { static int *pi = &i; // Error in C static void ( *pf )( void ) = &func1; // Address of thunk in C, // function in C++ }
Toutefois, étant donné qu’un programme qui inclut l’attribut
dllexport
dans la déclaration d’un objet doit fournir la définition de cet objet quelque part dans le programme, vous pouvez initialiser un pointeur de fonction statique global ou local avec l’adresse d’unedllexport
fonction. De même, vous pouvez initialiser un pointeur de données statiques global ou local avec l'adresse d'un objet de donnéesdllexport
. Par exemple, le code suivant ne génère pas d'erreur en C ni en C++ :__declspec( dllexport ) void func1( void ); __declspec( dllexport ) int i; int *pi = &i; // Okay static void ( *pf )( void ) = &func1; // Okay void func2() { static int *pi = &i; // Okay static void ( *pf )( void ) = &func1; // Okay }
Si vous appliquez
dllexport
à une classe régulière qui a une classe de base qui n’est pas marquée commedllexport
étant, le compilateur génère C4275.Le compilateur génère le même avertissement si la classe de base est une spécialisation d'un modèle de classe. Pour contourner ce problème, marquez la classe de base avec
dllexport
. Le problème avec une spécialisation d’un modèle de classe est l’emplacement où placer le__declspec(dllexport)
; vous n’êtes pas autorisé à marquer le modèle de classe. Au lieu de cela, instanciez explicitement le modèle de classe et marquez cette instanciation explicite avecdllexport
. Par exemple :template class __declspec(dllexport) B<int>; class __declspec(dllexport) D : public B<int> { // ...
Cette solution de contournement échoue si l’argument template est la classe dérivée. Par exemple :
class __declspec(dllexport) D : public B<D> { // ...
Étant donné qu’il s’agit d’un modèle courant avec des modèles, le compilateur a modifié la sémantique du
dllexport
moment où il est appliqué à une classe qui a une ou plusieurs classes de base et lorsqu’une ou plusieurs classes de base est une spécialisation d’un modèle de classe. Dans ce cas, le compilateur s’appliquedllexport
implicitement aux spécialisations des modèles de classe. Vous pouvez effectuer les opérations suivantes et ne pas recevoir d’avertissement :class __declspec(dllexport) D : public B<D> { // ...
FIN de la section spécifique à Microsoft
Voir aussi
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour