Regole generali e limitazioni
Specifici di Microsoft
Se si dichiara una funzione o un oggetto senza dllimport o dllexport l'attributo, la funzione o l'oggetto non viene considerato parte dell'interfaccia DLL.Di conseguenza, la definizione della funzione o dell'oggetto sia presente in tale modulo o in un altro modulo dello stesso programma.Per fare parte dell'oggetto funzione o dell'interfaccia DLL, è necessario dichiarare la definizione della funzione o dell'oggetto in un altro modulo come dllexport.In caso contrario, verrà generato un errore del linker viene generato.
Se si dichiara una funzione o un oggetto con dllexport l'attributo, la relativa definizione deve trovarsi in un modulo dello stesso programma.In caso contrario, verrà generato un errore del linker viene generato.
Se un singolo modulo nel programma contiene entrambi dllimport e dllexport le dichiarazioni per lo stesso esecuzione o oggetto, dllexport l'attributo ha la precedenza su dllimport attributo.Tuttavia, un avviso del compilatore viene generato.Di seguito è riportato un esempio:
__declspec( dllimport ) int i; __declspec( dllexport ) int i; // Warning; inconsistent; // dllexport takes precedence.
In C++, è possibile inizializzare un puntatore ai dati locale dichiarata a livello globale o statica o con l'indirizzo di un oggetto dati dichiarato con dllimport attributo, che genera un errore in C#.Inoltre, è possibile inizializzare un puntatore a funzione locale statico con l'indirizzo di una funzione dichiarata con dllimport attributo.In C#, tale assegnazione imposta il puntatore all'indirizzo del thunk di importazione della DLL (uno stub di codice che trasferisce il controllo alla funzione) anziché l'indirizzo della funzione.In C++, imposta il puntatore all'indirizzo della funzione.Di seguito è riportato un esempio:
__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++ }
Tuttavia, un programma che includa dllexport l'attributo nella dichiarazione di un oggetto deve fornire la definizione di tale oggetto in un punto qualsiasi del programma, è possibile inizializzare un puntatore a funzione statica globale o locale con l'indirizzo di un oggetto dllexport funzione.Analogamente, è possibile inizializzare un puntatore ai dati statici globali o locali con l'indirizzo di un oggetto dllexport oggetto dati.Ad esempio, il codice seguente non genera errori in c o 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 }
A causa di una modifica nel comportamento introdurre in Visual C++ .NET per renderla di dllexport più coerente tra le normali classi e le specializzazioni di template di classe, se si applica dllexport in una classe normale con una classe base non è contrassegnata come dllexport, il compilatore genererà C4275.
Il compilatore genera lo stesso avviso se la classe base è una specializzazione di template di classe.Per ovviare a questo problema, contrassegnare la classe base con dllexport.Il problema con una specializzazione di template di classe consente di posizionare __declspec (dllexport); non è consentito per contrassegnare il modello di classe.Al contrario, la creazione esplicita di un'istanza del modello della classe e contrassegnare la creazione di istanza esplicita con dllexport.Di seguito è riportato un esempio:
template class __declspec(dllexport) B<int>; class __declspec(dllexport) D : public B<int> { // ...
Questa soluzione alternativa si verifica se l'argomento di modello è la classe di derivazione.Di seguito è riportato un esempio:
class __declspec(dllexport) D : public B<D> { // ...
Poiché si tratta di modello comune con i modelli, il compilatore modificava la semantica di dllexport quando viene applicato a una classe che contiene una o più classi base e quando uno o più delle classi di base è una specializzazione di template di classe.In questo caso, il compilatore in modo implicito viene applicata dllexport le specializzazioni dei modelli della classe.In Visual C++ .NET, un utente può eseguire le operazioni seguenti e non ricevere un avviso:
class __declspec(dllexport) D : public B<D> { // ...