Allgemeine Regeln und Einschränkungen
Microsoft-spezifisch
Wenn Sie eine Funktion oder ein Objekt ohne das
dllimport
Attributdllexport
deklarieren, wird die Funktion oder das Objekt nicht als Teil der DLL-Schnittstelle betrachtet. Daher muss die Definition der Funktion oder des Objekts in diesem Modul oder in einem anderen Modul desselben Programms vorhanden sein. Um die Funktion oder das Objekt teil der DLL-Schnittstelle zu machen, müssen Sie die Definition der Funktion oder des Objekts im anderen Modul alsdllexport
deklarieren. Andernfalls wird ein Linkerfehler generiert.Wenn Sie eine Funktion oder ein Objekt mit dem
dllexport
Attribut deklarieren, muss die Definition in einem Modul desselben Programms angezeigt werden. Andernfalls wird ein Linkerfehler generiert.Wenn ein einzelnes Modul in Ihrem Programm sowohl Deklarationen als auch
dllimport
dllexport
Deklarationen für dieselbe Funktion oder dasselbe Objekt enthält, hat dasdllexport
Attribut Vorrang vor demdllimport
Attribut. Es wird jedoch eine Compilerwarnung ausgegeben. Beispiel:__declspec( dllimport ) int i; __declspec( dllexport ) int i; // Warning; inconsistent; // dllexport takes precedence.
In C++ können Sie einen global deklarierten oder statischen lokalen Datenzeiger oder die Adresse eines mit dem
dllimport
Attribut deklarierten Datenobjekts initialisieren, das einen Fehler in C generiert. Darüber hinaus können Sie einen statischen lokalen Funktionszeiger mit der Adresse einer Funktion initialisieren, die mit demdllimport
Attribut deklariert ist. In C legt eine solche Zuweisung den Zeiger auf die Adresse des DLL-Importthunks (ein Codestub, der die Steuerung an die Funktion übergibt) anstatt auf die Adresse der Funktion fest. In C++ wird der Zeiger auf die Adresse der Funktion festgelegt. Beispiel:__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++ }
Da jedoch ein Programm, das das
dllexport
Attribut in die Deklaration eines Objekts einschließt, die Definition für dieses Objekt irgendwo im Programm bereitstellen muss, können Sie einen globalen oder lokalen statischen Funktionszeiger mit der Adresse einerdllexport
Funktion initialisieren. Ebenso können Sie einen globalen oder lokalen statischen Datenzeiger mit der Adresse einesdllexport
-Datenobjekts initialisieren. Zum Beispiel generiert der folgende Code keine Fehler in C oder 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 }
Wenn Sie auf eine normale Klasse anwenden
dllexport
, die über eine Basisklasse verfügt, die nicht alsdllexport
gekennzeichnet ist, generiert der Compiler C4275.Der Compiler generiert dieselbe Warnung, wenn die Basisklasse eine Spezialisierung einer Klassenvorlage ist. Um dies zu umgehen, markieren Sie die Basisklasse mit
dllexport
. Das Problem mit einer Spezialisierung einer Klassenvorlage besteht darin, wo die__declspec(dllexport)
Klassenvorlage platziert werden soll. Sie dürfen die Klassenvorlage nicht markieren. Instanziieren Sie stattdessen die Klassenvorlage explizit, und markieren Sie diese explizite Instanziierung mitdllexport
. Beispiel:template class __declspec(dllexport) B<int>; class __declspec(dllexport) D : public B<int> { // ...
Diese Problemumgehung funktioniert nicht, wenn das Vorlagenargument die ableitende Klasse ist. Beispiel:
class __declspec(dllexport) D : public B<D> { // ...
Da dies gängige Muster mit Vorlagen ist, hat der Compiler die Semantik
dllexport
geändert, wenn sie auf eine Klasse angewendet wird, die eine oder mehrere Basisklassen enthält und wenn eine oder mehrere Basisklassen eine Spezialisierung einer Klassenvorlage sind. In diesem Fall gilt der Compiler implizit fürdllexport
die Spezialisierungen von Klassenvorlagen. Sie können die folgenden Aktionen ausführen und keine Warnung erhalten:class __declspec(dllexport) D : public B<D> { // ...
Ende Microsoft-spezifisch
Siehe auch
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für