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ż, że AFX_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 CWinAppklasy , 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 biblioteki 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 obiektem CWinApppochodnym aplikacji klienckiej. Oznacza to, że aplikacja kliencka jest właścicielem głównej pompy komunikatów, pętli bezczynności itd.

  • Wywołuje AfxInitExtensionModuleDllMain funkcję . Należy sprawdzić wartość zwracaną tej funkcji. Jeśli zwracana jest wartość zero z AfxInitExtensionModulefunkcji , zwróć wartość 0 z DllMain 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 pliku 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. Retail MFCx0.dll ma około 2000 wyeksportowanych punktów wejścia; debugowanie pliku MFCx0D.dll ma około 3000 wyeksportowanych punktów wejścia.

Zarządzanie pamięcią

Biblioteka 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 sam plik 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. Przykład użycia tego podejścia do jawnego załadowania menu można znaleźć w temacie 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.

Biblioteka MFCxx.dll jest zwykle ostatnia na liście zasobów i klas. Biblioteka MFCxx.dll zawiera wszystkie standardowe zasoby MFC, w tym ciągi monitów 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 pliku 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?

Zobacz też

Tworzenie bibliotek DLL języka C/C++ w programie Visual Studio