Obecná pravidla a omezení
Konkrétní společnosti Microsoft
Je-li deklarovat funkci nebo objekt bez dllimport nebo dllexport atribut, funkce nebo objektu nejsou považovány za součást knihovny DLL rozhraní.Proto musí být definice funkce nebo objektu přítomna v modulu nebo jiného modulu stejný program.Chcete-li funkci nebo objekt součástí rozhraní knihovny DLL, musíte deklarovat definice funkce nebo objekt jako modul dllexport.Jinak je generována chyba linker.
Je-li deklarovat funkci nebo objekt s dllexport atribut jeho definice musí být v některých modul stejný program.Jinak je generována chyba linker.
Pokud jeden modul v programu obsahuje obě dllimport a dllexport prohlášení pro stejnou funkci nebo objekt, dllexport atribut přednost dllimport atribut.Však je generována upozornění kompilátoru.Příklad:
__declspec( dllimport ) int i; __declspec( dllexport ) int i; // Warning; inconsistent; // dllexport takes precedence.
V jazyce C++ může inicializovat místní data globálně prohlášené nebo statické ukazatele nebo s adresou datový objekt s dllimport atribut, který vygeneruje chybu v C.Kromě toho můžete inicializovat statické místní funkce ukazatel s adresou funkce deklarované s dllimport atributu.Takové přiřazení v C, nastaví ukazatel na adresu jádro import knihovny DLL (rámec kódu, který předává řízení funkce) namísto adresy funkce.V jazyce C++ nastaví ukazatel na adresu funkce.Příklad:
__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++ }
Však, protože program, který obsahuje dllexport v prohlášení objektu atributu musí poskytovat definice objektu někde v programu, můžete inicializovat globální nebo místní statická funkce ukazatel s adresou dllexport funkce.Podobně můžete inicializovat globální nebo místní statická data ukazatele s adresou dllexport data objektu.Například následující kód chyby v c nebo C++ negeneruje:
__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 }
Z důvodu změny v chování zaveďte v jazyce C++.NET je použití dllexport konzistentnější mezi běžných třídách a odborností šablony třídy, pokud použijete dllexport do běžné třídy, která má základní třídy, které nejsou označeny jako dllexport, kompilátor vygeneruje C4275.
Kompilátor generuje stejné upozornění, pokud je základní třída šablony třídy.Chcete-li tento problém vyřešit, označit základní třída s dllexport.Problém s specializace šablony třídy je umístění __declspec(dllexport); není dovoleno označit šablonu třídy.Místo toho explicitně vytvořit instanci šablony třídy a označit tento explicitní instance s dllexport.Příklad:
template class __declspec(dllexport) B<int>; class __declspec(dllexport) D : public B<int> { // ...
Toto řešení selže, pokud je argument šablona třídy deriving.Příklad:
class __declspec(dllexport) D : public B<D> { // ...
Toto je společný vzorek šablony, kompilátor změněna sémantika dllexport u třídy, která má jeden nebo více base tříd a jeden nebo více základních tříd je šablonu třídy.V tomto případě kompilátor implicitně vztahuje dllexport s odborností šablony třídy.V jazyce C++.NET, uživatel můžete provést následující a získat upozornění:
class __declspec(dllexport) D : public B<D> { // ...