Importy wzajemne
Eksportowanie lub importowanie do innego pliku wykonywalnego przedstawia komplikacje podczas przywozu są wzajemne (lub kołowy).Na przykład dwa pliki dll importować symbole od siebie, podobne do wzajemnie rekurencyjnych.
Problem z wzajemnie importowanie plików wykonywalnych (zazwyczaj pliki dll) jest, że nie może być zbudowany bez tworzenia innych pierwszy.Każdy proces budowania wymaga jako dane wejściowe, import biblioteki produkowane przez proces kompilacji.
Rozwiązaniem jest wykorzystanie narzędzia LIB z opcją /DEF, która produkuje import biblioteki bez tworzenia pliku wykonywalnego.Za pomocą tego narzędzia, można zbudować wszystkich bibliotek importu konieczne, niezależnie od tego, jak wiele bibliotek DLL są zaangażowane lub jak skomplikowane są zależności.
Ogólne rozwiązanie do obsługi wzajemnego przywozu jest:
Z kolei podjęcia każdej biblioteki DLL. (Dowolnej kolejności jest możliwe, chociaż niektóre zamówienia są bardziej optymalne.) Jeśli istnieją wszystkie biblioteki import potrzebne są aktualne, uruchom łącze zbudować plik wykonywalny (DLL).Tworzy bibliotekę importu.W przeciwnym razie uruchom LIB do produkcji import biblioteki.
Uruchamianie LIB z opcją /DEF powoduje dodatkowy plik z.Rozszerzenie EXP..Konieczne jest użycie pliku EXP później zbudować plik wykonywalny.
Po użyciu łącza lub LIB zbudować wszystkie biblioteki import, wróć i uruchomić łącze do budowy wszelkich plików wykonywalnych, które nie zostały zbudowane w poprzednim kroku.Należy zauważyć, że odpowiedni plik .exp musi być określona w wierszu łącze.
Po uruchomieniu narzędzia LIB wcześniej do produkcji import biblioteki dla DLL1, LIB może wytworzony pliku DLL1.exp, jak również.Należy użyć DLL1.exp jako dane wejściowe do łącza podczas konstruowania DLL1.dlll.
Na poniższej ilustracji przedstawiono rozwiązanie dla dwóch wzajemnie przywozu biblioteki dll, DLL1 i DLL2.Krok 1 jest uruchomienie LIB, z /DEF zestaw opcji, na DLL1.Krok 1 produkuje DLL1.lib, import biblioteki i DLL1.exp.W kroku 2 import biblioteki służy do budowania DLL2, która z kolei produkuje import biblioteki symboli w DLL2.Krok 3 tworzy DLL1, przy użyciu DLL1.exp i DLL2.lib jako dane wejściowe.Należy zauważyć, że plik .exp dla DLL2 nie jest konieczne, ponieważ LIB nie wykorzystano do budowy DLL2's import biblioteki.
Dwa pliki dll z przywozem wzajemne łączenie
Ograniczenia _AFXEXT
Można użyć _AFXEXT preprocesora symbol dla rozszerzenia tak długo, jak nie masz wiele warstw bibliotek DLL rozszerzeń biblioteki dll.Jeśli mają rozszerzenie biblioteki dll, które zadzwonić lub pochodzić od klasy w własne rozszerzenie bibliotek DLL, które następnie pochodzić od klasy MFC, należy użyć symbolu preprocesora w celu uniknięcia niejednoznaczności.
Problem polega na tym miasto Win32, musi jawnie deklarować, że wszelkie dane jako __declspec(dllexport) Jeśli jest przeznaczony do wywozu z biblioteki DLL, i __declspec(dllimport) w celu zaimportowania z biblioteki DLL.Po zdefiniowaniu _AFXEXT, nagłówki MFC, upewnij się, że AFX_EXT_CLASS jest poprawnie zdefiniowany.
Kiedy masz wiele warstw, jeden symbol takich jak AFX_EXT_CLASS nie jest wystarczające, ponieważ biblioteka DLL rozszerzenia może być eksportowanie nowych klas, a także importowanie innych klas z innej biblioteki DLL rozszerzenia.Aby rozwiązać ten problem, Użyj specjalnych preprocesora symbol, który wskazuje budują DLL porównaniu z wykorzystaniem biblioteki DLL.Załóżmy na przykład, dwa rozszerzenia biblioteki dll, A.dll i B.dll.Każdy z nich wyeksportować niektórych klas w A.h i B.h, odpowiednio.B.dll korzysta z klas z A.dll.Pliki nagłówków będzie wyglądać mniej więcej tak:
/* A.H */
#ifdef A_IMPL
#define CLASS_DECL_A __declspec(dllexport)
#else
#define CLASS_DECL_A __declspec(dllimport)
#endif
class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };
// B.H
#ifdef B_IMPL
#define CLASS_DECL_B __declspec(dllexport)
#else
#define CLASS_DECL_B __declspec(dllimport)
#endif
class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition ... };
...
Podczas A.dll, jest zbudowany z /D A_IMPL i B.dll jest zbudowany, jest zbudowany z /D B_IMPL.Za pomocą oddzielnych symbole dla każdej biblioteki DLL, CExampleB jest eksportowany i CExampleA jest importowany podczas konstruowania B.dll.CExampleAjest wywożone podczas konstruowania A.dll i przywożone, gdy jest używana przez B.dll (lub innego klienta).
Nie można wykonać tego rodzaju warstw, korzystając z wbudowanych AFX_EXT_CLASS i _AFXEXT symboli preprocesora.Techniki opisane powyżej rozwiązuje ten problem w sposób nie w przeciwieństwie do mechanizmu MFC, sam używa podczas konstruowania jego technologii Active, bazy danych i biblioteki DLL rozszerzenia sieci.
Nie dokonywał wywozu całej klasy
Jeśli nie eksportujesz całej klasy, musisz zapewnić poprawnie wyeksportować elementy niezbędne dane utworzone przez makra MFC.Można to zrobić poprzez przedefiniowanie AFX_DATA do makra określonej klasy.Należy to zrobić dowolnym czasie nie eksportujesz całej klasy.
Na przykład:
/* A.H */
#ifdef A_IMPL
#define CLASS_DECL_A _declspec(dllexport)
#else
#define CLASS_DECL_A _declspec(dllimport)
#endif
#undef AFX_DATA
#define AFX_DATA CLASS_DECL_A
class CExampleA : public CObject
{
DECLARE_DYNAMIC()
CLASS_DECL_A int SomeFunction();
//... class definition ...
};
#undef AFX_DATA
#define AFX_DATA