Biblioteki DLL rozszerzeń MFC
Biblioteka DLL rozszerzenia MFC to biblioteka DLL, która zazwyczaj implementuje klasy wielokrotnego użytku pochodzące z istniejących klas bibliotek klas programu Microsoft Foundation.
Biblioteka DLL rozszerzenia MFC ma następujące funkcje i wymagania:
Plik wykonywalny klienta musi być aplikacją MFC skompilowana ze zdefiniowaną definicją
_AFXDLL
.Biblioteka DLL rozszerzenia MFC może być również używana przez zwykłą bibliotekę MFC DLL, która jest dynamicznie połączona z MFC.
Biblioteki DLL rozszerzeń MFC powinny być kompilowane ze zdefiniowanymi bibliotekami
_AFXEXT
DLL. Siły_AFXDLL
te należy również zdefiniować i zapewnić, że odpowiednie deklaracje są pobierane z plików nagłówków MFC. Gwarantuje to również, żeAFX_EXT_CLASS
jest definiowany jako__declspec(dllexport)
podczas kompilowania biblioteki DLL, co jest konieczne, jeśli używasz tego makra do deklarowania klas w dll rozszerzenia MFC.Biblioteki DLL rozszerzeń MFC nie powinny utworzyć wystąpienia klasy pochodzącej z
CWinApp
klasy , ale powinny polegać na aplikacji klienckiej (lub dll) w celu udostępnienia tego obiektu.Biblioteki DLL rozszerzeń MFC powinny jednak zapewniać
DllMain
funkcję i wykonywać tam wszelkie niezbędne inicjowanie.
Biblioteki DLL rozszerzeń są tworzone przy użyciu dynamicznej wersji biblioteki MFC (znanej również jako udostępniona wersja MFC). Tylko pliki wykonywalne MFC (aplikacje lub zwykłe biblioteki DLL MFC), które są kompilowane z udostępnioną wersją MFC, mogą używać biblioteki DLL rozszerzenia MFC. Zarówno aplikacja kliencka, jak i biblioteka DLL rozszerzenia MFC muszą używać tej samej wersji MFCx0.dll. Dzięki biblioteki DLL rozszerzenia MFC można utworzyć nowe klasy niestandardowe z MFC, a następnie zaoferować tę rozszerzoną wersję MFC aplikacjom wywołującym bibliotekę DLL.
Biblioteki DLL rozszerzeń mogą być również używane do przekazywania obiektów pochodnych MFC między aplikacją a biblioteką DLL. Funkcje składowe skojarzone z przekazanym obiektem istnieją w module, w którym został utworzony obiekt. Ponieważ te funkcje są prawidłowo eksportowane podczas korzystania z udostępnionej wersji biblioteki DLL MFC, można swobodnie przekazywać wskaźniki obiektów pochodnych MFC lub MFC między aplikacją a bibliotekami DLL rozszerzeń MFC, które ładuje.
Biblioteka DLL rozszerzenia MFC używa udostępnionej wersji MFC w taki sam sposób, jak aplikacja używa udostępnionej wersji biblioteki DLL MFC, z kilkoma dodatkowymi zagadnieniami:
Nie ma obiektu pochodnego
CWinApp
. Musi działać z obiektemCWinApp
pochodnym aplikacji klienckiej. Oznacza to, że aplikacja kliencka jest właścicielem głównej pompy komunikatów, pętli bezczynności itd.Wywołuje
AfxInitExtensionModule
DllMain
funkcję . Należy sprawdzić wartość zwracaną tej funkcji. Jeśli zwracana jest wartość zero zAfxInitExtensionModule
funkcji , zwróć wartość 0 zDllMain
funkcji.Tworzy obiekt CDynLinkLibrary podczas inicjowania, jeśli biblioteka DLL rozszerzenia MFC chce wyeksportować
CRuntimeClass
obiekty lub zasoby do aplikacji.
Przed wersją 4.0 MFC ten typ biblioteki DLL był nazywany AFXDLL. AFXDLL odwołuje się do symbolu preprocesora zdefiniowanego _AFXDLL
podczas kompilowania biblioteki DLL.
Biblioteki importu dla udostępnionej wersji MFC są nazwane zgodnie z konwencją opisaną w konwencji nazewnictwa bibliotek DLL MFC. Program Visual Studio dostarcza wstępnie utworzone wersje bibliotek DLL MFC oraz wiele bibliotek DLL innych niż MFC, których można używać i rozpowszechniać w aplikacjach. Są one udokumentowane w Redist.txt, który jest instalowany w folderze Program Files\Microsoft Visual Studio.
Jeśli eksportujesz przy użyciu pliku def, umieść następujący kod na początku i na końcu pliku nagłówka:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA
Te cztery wiersze zapewniają poprawne skompilowanie kodu dla biblioteki DLL rozszerzenia MFC. Pozostawienie tych czterech wierszy może spowodować niepoprawne skompilowanie lub połączenie biblioteki DLL.
Jeśli musisz przekazać wskaźnik obiektu pochodnego MFC lub MFC do lub z biblioteki DLL MFC, biblioteka DLL powinna być biblioteką DLL rozszerzenia MFC. Funkcje składowe skojarzone z przekazanym obiektem istnieją w module, w którym został utworzony obiekt. Ponieważ te funkcje są prawidłowo eksportowane podczas korzystania z udostępnionej wersji biblioteki DLL MFC, można swobodnie przekazywać wskaźniki obiektów pochodnych MFC lub MFC między aplikacją a bibliotekami DLL rozszerzeń MFC, które ładuje.
Ze względu na problemy z zarządzaniem i eksportowaniem nazw języka C++ lista eksportu z biblioteki DLL rozszerzenia MFC może być inna między debugowaniem a wersjami detalicznymi tej samej biblioteki DLL i bibliotek DLL dla różnych platform. MFCx0.dll handlu detalicznego ma około 2000 wyeksportowanych punktów wejścia; MFCx0D.dll debugowania ma około 3000 wyeksportowanych punktów wejścia.
Zarządzanie pamięcią
MFCx0.dll i wszystkie biblioteki DLL rozszerzeń MFC załadowane do przestrzeni adresowej aplikacji klienckiej używają tego samego alokatora pamięci, ładowania zasobów i innych stanów globalnych MFC tak, jakby znajdowały się w tej samej aplikacji. Jest to istotne, ponieważ biblioteki DLL inne niż MFC i zwykłe biblioteki DLL MFC działają dokładnie odwrotnie i mają każdą bibliotekę DLL przydzielaną z własnej puli pamięci.
Jeśli biblioteka DLL rozszerzenia MFC przydziela pamięć, ta pamięć może swobodnie przeplatać się z dowolnym innym obiektem przydzielonym przez aplikację. Ponadto jeśli aplikacja, która dynamicznie łączy się z MFC, nie powiedzie się, ochrona systemu operacyjnego zachowuje integralność dowolnej innej aplikacji MFC współużytkowania biblioteki DLL.
Podobnie inne globalne stany MFC, takie jak bieżący plik wykonywalny do załadowania zasobów, są również współużytkowane przez aplikację klienczą i wszystkie biblioteki DLL rozszerzeń MFC, a także same MFCx0.dll.
Udostępnianie zasobów i klas
Eksportowanie zasobów odbywa się za pośrednictwem listy zasobów. Każda aplikacja zawiera singly połączoną listę obiektów CDynLinkLibrary . Jeśli szukasz zasobu, większość standardowych implementacji MFC, które ładują zasoby, najpierw przyjrzyj się bieżącemu modułowi zasobów (AfxGetResourceHandle
), a jeśli zasób nie zostanie znaleziony, przejdź do listy obiektów CDynLinkLibrary próbujących załadować żądany zasób.
Przejście do listy ma wady, które są nieco wolniejsze i wymagają zarządzania zakresami identyfikatorów zasobów. Ma to zaletę, że aplikacja kliencka, która łączy się z kilkoma bibliotekami DLL rozszerzeń MFC, może używać dowolnego zasobu dostarczonego przez bibliotekę DLL bez konieczności określania uchwytu wystąpienia biblioteki DLL. AfxFindResourceHandle
to interfejs API służący do chodzenia po liście zasobów w celu wyszukania danego dopasowania. Przyjmuje nazwę i typ zasobu i zwraca uchwyt zasobu, w którym został znaleziony po raz pierwszy (lub NULL).
Jeśli nie chcesz przechodzić do listy i ładować tylko zasoby z określonego miejsca, użyj funkcji AfxGetResourceHandle
i AfxSetResourceHandle
zapisz stary uchwyt i ustaw nowy uchwyt. Pamiętaj, aby przywrócić stary uchwyt zasobu przed powrotem do aplikacji klienckiej. Aby zapoznać się z przykładem użycia tego podejścia do jawnego załadowania menu, zobacz Testdll2 .cpp w przykładowej biblioteki DLLHUSK MFC.
Dynamiczne tworzenie obiektów MFC przy użyciu nazwy MFC jest podobne. Mechanizm deserializacji obiektów MFC musi zawierać wszystkie CRuntimeClass
zarejestrowane obiekty, aby można je było odtworzyć dynamicznie tworząc obiekty języka C++ wymaganego typu na podstawie tego, co było przechowywane wcześniej.
W przypadku przykładowej biblioteki DLLHUSK MFC lista wygląda następująco:
head -> DLLHUSK.EXE - or - DLLHUSK.EXE
| |
TESTDLL2.DLL TESTDLL2.DLL
| |
TESTDLL1.DLL TESTDLL1.DLL
| |
MFCOxxD.DLL |
| |
MFCDxxD.DLL |
| |
MFCxxD.DLL MFCxx.DLL
gdzie xx jest numerem wersji, na przykład 42 reprezentuje wersję 4.2.
MFCxx.dll zazwyczaj znajduje się na liście zasobów i klas. MFCxx.dll zawiera wszystkie standardowe zasoby MFC, w tym ciągi monitu dla wszystkich standardowych identyfikatorów poleceń. Umieszczenie go na końcu listy umożliwia biblioteki DLL i samej aplikacji klienckiej, aby nie mieć własnej kopii standardowych zasobów MFC, ale polegać na udostępnionych zasobach w MFCxx.dll.
Scalanie zasobów i nazw klas wszystkich bibliotek DLL z przestrzenią nazw aplikacji klienckiej ma wadę wymaga, aby zachować ostrożność przy użyciu wybranych identyfikatorów lub nazw.
Przykład DLLHUSK zarządza przestrzenią nazw zasobów udostępnionych przy użyciu wielu plików nagłówkowych.
Jeśli biblioteka DLL rozszerzenia MFC musi obsługiwać dodatkowe dane dla każdej aplikacji, możesz utworzyć nową klasę z biblioteki CDynLinkLibrary i utworzyć ją w pliku DllMain
. Podczas uruchamiania biblioteka DLL może sprawdzić listę obiektów CDynLinkLibrary bieżącej aplikacji, aby znaleźć ten dla tej konkretnej biblioteki DLL rozszerzenia MFC.
Co chcesz zrobić?
Co chcesz dowiedzieć się więcej?
Porady dotyczące korzystania z udostępnionych plików zasobów
Używanie bibliotek DLL baz danych, OLE i rozszerzeń MFC gniazd w zwykłych bibliotekach MFC DLL
Zobacz też
Tworzenie bibliotek DLL języka C/C++ w programie Visual Studio