Korzystanie z dllimport i dllexport w klasach C++
Specyficzne dla firmy Microsoft
Możesz zadeklarować klasy C++ za pomocą atrybutu dllimport lub dllexport.Te formularze znaczą, że cała klasa jest zaimportowana lub wyeksportowana.Klasy wyeksportowane w ten sposób są nazywane klasami, które można eksportować.
W poniższym przykładzie zdefiniowano klasę, którą można eksportować.Wszystkie jego funkcje składowe i dane statyczne są eksportowane:
#define DllExport __declspec( dllexport )
class DllExport C {
int i;
virtual int func( void ) { return 1; }
};
Należy zauważyć, że jawne użycie atrybutów dllimport i dllexport na elementach członkowskich klas eksportowalnych jest zabronione
Klasy dllexport
Kiedy deklarujesz klasę dllexport, wszystkie jej funkcje członkowskie i członkowskie dane statyczne są eksportowane.Należy dostarczyć definicje wszystkich takich członków w tym samym programie.W przeciwnym wypadku zostanie wygenerowany błąd konsolidatora.Jeden wyjątek od tej reguły odnosi się do czystych funkcji wirtualnych, dla których nie trzeba dostarczyć wyraźnych definicji.Jednak, ponieważ destruktor klasy abstrakcyjnej zawsze jest wywoływany przez destruktor klasy podstawowej, czysto wirtualne destruktory muszą zawsze dostarczać definicję.Należy zauważyć, że te zasady są takie same dla klasy nieeksportowalnej.
Podczas eksportowania danych typu klasy lub funkcji, które zwracają klasy, należy wyeksportować klasy.
Klasy dllexport
Kiedy deklarujesz klasę dllimport, wszystkie jej funkcje członkowskie i członkowskie dane statyczne są importowane.W odróżnieniu od zachowania dllimport a dllexport w typach nieklasowych, elementy członkowskie danych statycznych nie mogą określać definicji w tym samym programie, w którym zdefiniowana jest klasa dllimport.
Dziedziczenie i możliwe do eksportowania klasy
Wszystkie klasy podstawowej klasy możliwuje do eksportowania muszą być możliwe do eksportowania.Jeśli nie, kompilator wygeneruje ostrzeżenie.Ponadto wszystkie dostępne elementy członkowskie, które są również klasami muszą być możliwe do eksportowania.Ta reguła pozwala klasie dllexport dziedziczyć od klasy dllimport i klasie dllimport dziedziczyć od klasy dllexport (ostanie nie jest jednak zalecane).Co do zasady, wszystko, co jest dostępne dla klienta biblioteki DLL (według zasady dostępu do C++) powinno być częścią interfejsu, który można eksportować.Obejmuje to elementy członkowskie danych prywatnych z odwołaniem w funkcjach wbudowanych.
Selektywny element członkowski importu/eksportu
Ponieważ funkcje składowe i dane statyczne w klasie są niejawnie powiązania zewnętrzne, można zadeklarować je z elementu dllimport lub dllexport atrybutu, chyba że cała klasa jest eksportowana.Jeśli cała klasa jest importowana lub eksportowana, jawna deklaracja funkcji członkowskich i dane w postaci dllimport lub dllexport są zabronione.Jeśli zadeklarujesz statyczny element członkowski danych w ramach definicji klasy jako dllexport, definicja musi wystąpić gdzieś w ramach tego samego programu (tak jak w przypadku powiązania zewnętrznego braku klasy).
Podobnie, można zadeklarować funkcje członkowskie z atrybutami dllimport lub dllexport.W tym przypadku należy podać definicję dllexport w obrębie tego samego programu.
Warto pamiętać o kilku istotnych kwestiach dotyczących selektywnego importu i eksportu elementu członkowskiego:
Selektywny element członkowski importu/eksportu najlepiej nadaje się do dostarczania wersji interfejsu klasy wyeksportowanej, która jest bardziej restrykcyjna; czyli takiej, dla której można zaprojektować bibliotekę DLL, która udostępnia mniej funkcji publicznych i prywatnych, niż umożliwiłby to język w przeciwnym razie.Jest on również przydatny do precyzyjnego dostosowywania interfejsu, który można eksportować, gdy wiadomo, że klient, zgodnie z definicją, nie jest w stanie uzyskać dostępu do niektórych danych prywatnych; nie trzeba eksportować całej klasy.
Podczas eksportowania jednej wirtualnej funkcji w klasie, musisz je wszystkie wyeksportować lub przynajmniej dostarczyć wersje, które klient może używać bezpośrednio.
Jeśli posiadasz klasę, w której wykorzystujesz selektywny członkowski import/eksport z funkcjami wirtualnymi, funkcje muszą znajdować się w interfejsie, nadającym się do eksportu lub zdefiniowanej instrukcji inline (widoczne dla klienta).
Jeśli określisz element członkowski jako dllexport , ale nie umieścisz go w definicji klasy, zostanie wygenerowany błąd kompilatora.Należy zdefiniować nagłówek dla elementu członkowskiego i klasy.
Mimo, że definicja klasy członków jako elementu dllimport lub dllexport jest dozwolona, nie może zastąpić interfejsu określonego w definicji klasy.
W przypadku zdefiniowania funkcji członkowskiej w miejscu innym niż ciało definicji klasy, w której została zadeklarowana, zostanie wygenerowane ostrzeżenie, jeśli funkcja została zdefiniowana jako dllexport lub dllimport (jeśli definicja ta różni się od podanej w deklaracji klasy).