Règles générales et limitations
Spécifique à Microsoft
Si vous déclarez une fonction ou un objet sans attribut de dllimport ou d' dllexport , la fonction ou l'objet n'est pas considérée comme une partie de l'interface DLL.Par conséquent, la définition de la fonction ou de l'objet doit être présent dans ce module ou d'un autre module du même programme.Pour que la fonction ou la partie d'objet de l'interface DLL, vous devez déclarer la définition de la fonction ou de l'objet dans l'autre module comme dllexport.Sinon, une erreur de l'éditeur de liens est générée.
si vous déclarez une fonction ou un objet avec l'attribut d' dllexport , sa définition doit apparaître dans un certain module du même programme.Sinon, une erreur de l'éditeur de liens est générée.
Si un seul module dans votre programme contient dllimport et les déclarations d' dllexport pour la même fonction ou objet, l'attribut d' dllexport est prioritaire sur l'attribut de dllimport .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 données local globalement déclaré ou statique ou avec l'adresse d'un objet de données déclaré avec l'attribut de dllimport , qui génère une erreur en C.en outre, vous pouvez initialiser un pointeur fonction local statique avec l'adresse d'une fonction déclarée avec l'attribut de dllimport .En C, un tel peut-être définit le pointeur vers l'adresse de la conversion de code d'importation de la DLL (un stub de code qui transfère le contrôle à la fonction) plutôt que l'adresse de la fonction.En C++, il affecte le pointeur vers 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 d' dllexport dans la déclaration d'un objet doit fournir la définition de cet objet en cours dans le programme, vous pouvez initialiser un pointeur de fonction statique globale ou locale avec l'adresse d'une fonction d' dllexport .De même, vous pouvez initialiser un pointeur données statiques globales ou locales avec l'adresse d'un objet de données d' dllexport .Par exemple, le code suivant ne génère pas d'erreur en C ou 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 }
En raison d'une modification du comportement tapez dans Visual C++ .NET pour que l'application d' dllexport plus cohérente entre les classes normales et les spécialisations les modèles de classe, si vous appliquez dllexport à une classe normale qui a une classe de base qui n'est pas marquée comme dllexport, le compilateur générera 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 résoudre ce problème, marquez la classe de base avec dllexport.Le problème dans une spécialisation d'un modèle de classe est l'emplacement __declspec (dllexport); il ne vous permet pas de marquer le modèle de classe.Instanciez à la place, explicitement le modèle de classe et marquer cette instanciation explicite avec dllexport.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> { // ...
Comme il s'agit de modèle commun avec des modèles, le compilateur a modifié la sémantique d' dllexport lorsqu'il est appliqué à une classe qui a une ou plusieurs classes de base et lorsqu'un ou plusieurs des classes de base est une spécialisation d'un modèle de classe.Dans ce cas, le compilateur applique implicitement dllexport des spécialisations les modèles de classe.Dans Visual C++ .NET, un utilisateur peut faire le suivi et ne pas obtenir un avertissement :
class __declspec(dllexport) D : public B<D> { // ...