Zasady ogólne i ograniczenia
Programu Microsoft
Jeśli zadeklarować funkcję lub obiekt bez dllimport lub dllexport atrybut, funkcji lub obiektu nie jest uważany za część interfejsu biblioteki DLL.W związku z tym definicja funkcji lub obiekt musi być obecny w tym module lub w inny moduł tego samego programu.Aby funkcja lub obiekt części interfejsu biblioteki DLL, należy zadeklarować definicji funkcji lub obiekt w inny moduł jako dllexport.W przeciwnym wypadku zostanie wygenerowany błąd programu łączącego.
Jeśli zadeklarować funkcję lub obiekt z dllexport atrybutu, jego definicję muszą pojawiać się w niektórych moduł tego samego programu.W przeciwnym wypadku zostanie wygenerowany błąd programu łączącego.
Jeśli pojedynczy moduł w programie zawiera zarówno dllimport i dllexport deklaracje dla tej samej funkcji lub obiekt, dllexport atrybutu ma pierwszeństwo przed dllimport atrybut.Jednakże jest generowane ostrzeżenie kompilatora.Na przykład:
__declspec( dllimport ) int i; __declspec( dllexport ) int i; // Warning; inconsistent; // dllexport takes precedence.
W języku C++ można zainicjować wskaźnik globalnie zadeklarowanych lub statycznych danych lokalnych lub z adresem obiektu danych, zadeklarowanych z dllimport atrybut, który generuje błąd w C.Ponadto można zainicjować wskaźnik statyczne funkcja lokalnym o adresie funkcja zadeklarowana z dllimport atrybut.C takie przypisanie ustawia wskaźnik na adres thunk importu biblioteki DLL (Kod szczątkowy przenoszący kontrolę do funkcji) zamiast adresu funkcji.W języku C++ ustawia wskaźnik adresu funkcji.Na przykład:
__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++ }
Jednakże ponieważ program obejmuje dllexport atrybutu w deklaracji obiektu musi dostarczyć definicji dla tego obiektu, gdzieś w programie, można zainicjować wskaźnik funkcji statycznej globalny lub lokalny adres dllexport funkcji.Podobnie, można zainicjować wskaźnik globalny lub lokalny danych statycznych z adresem dllexport obiektu danych.Na przykład poniższy kod nie generować błędy w c lub 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 }
Z powodu zmiany w zachowaniu wprowadzić w programie Visual C++.NET do złożenia wniosku o dllexport bardziej spójne pomiędzy zwykłych klas i specjalizacji szablony klasy, jeśli zastosujesz dllexport do zwykłej klasy, zawierający klasy podstawowej, która nie jest oznaczony jako dllexport, kompilator wygeneruje C4275.
Kompilator generuje ostrzeżenie w tym samym, jeśli klasa podstawowa jest specjalizacji szablonu klasy.Aby obejść ten problem, należy oznaczyć klasa bazowa z dllexport.Problem z specjalizacji szablonu klasy jest miejsce opcję __declspec(dllexport); nie możesz oznaczyć szablonu klasy.Zamiast tego należy jawnie wystąpienia szablonu klasy i znak ten jawnego wystąpienia z dllexport.Na przykład:
template class __declspec(dllexport) B<int>; class __declspec(dllexport) D : public B<int> { // ...
To obejście nie powiedzie się, jeśli argument szablonu jest klasa wynikających.Na przykład:
class __declspec(dllexport) D : public B<D> { // ...
Ponieważ jest to wspólnego wzorca z szablonami, kompilator zmianie semantykę dllexport , gdy jest ono stosowane do klasy, która ma jeden lub więcej klasy base i gdy jedno lub więcej podstawowych klas jest specjalizacji szablonu klasy.W tym przypadku kompilator niejawnie dotyczy dllexport do specjalizacji klasy szablonów.W programie Visual C++.NET, użytkownik może wykonać następujące czynności i nie otrzymać ostrzeżenie:
class __declspec(dllexport) D : public B<D> { // ...