TN011: używanie MFC jako części biblioteki DLL
Uwaga ta opisuje regularnych bibliotek DLL, które pozwalają na korzystanie z biblioteki MFC jako część systemu Windows biblioteki dołączanej (dynamicznie DLL).Przyjęto założenie, że czytelnik jest obeznany z bibliotek DLL systemu Windows i sposobu ich tworzenia.Informacje MFC DLL rozszerzeń, z którego można utworzyć rozszerzeń biblioteki MFC, zobacz Wersji MFC DLL.
Biblioteka DLL interfejsów
Regularne bibliotek DLL założono interfejsy między aplikacją i biblioteki DLL są określone w funkcji jak C lub jawnie eksportowanych klas.Nie można wyeksportować interfejsu klasy MFC.
Jeśli zarówno bibliotekę DLL i aplikacji chcesz używać klasy MFC, oba mają do wyboru albo użyć udostępniona wersja biblioteki MFC lub statycznie połączyć z kopią bibliotek.Aplikacji i biblioteki DLL może używają jednej z wersji standardowej biblioteki MFC.
Regularne biblioteki DLL mają kilka zalet:
Aplikacja korzystająca z pliku DLL nie trzeba używać klasy MFC i nie ma to aplikacja Visual C++.
Z regularnych dll statycznie łączących się MFC rozmiar pliku dll zależy tylko procedur obsługi MFC i C, które są używane i połączone.
Z regularnych bibliotek DLL, które dynamicznie połączyć MFC mogą być znaczne oszczędności w pamięci używana jest udostępniona wersja biblioteki MFC.Jednakże, musisz rozpowszechnić współużytkowane biblioteki dll, biblioteki Mfc<version>.dll i Msvvcrt<version>.dll z biblioteki DLL.
Projekt DLL jest niezależna od sposobu implementacji klasy.Projekt DLL eksportuje tylko do interfejsów API ma.W rezultacie jeśli zmieni się wykonania, regularnych biblioteki DLL są nadal ważne.
Z regularnych dll statycznie łączących się MFC użycie zarówno DLL i aplikacji MFC, nie ma żadnych problemów z aplikacją, który chce innej wersji biblioteki MFC DLL lub na odwrót.Ponieważ biblioteki MFC statycznie jest związana w każdej biblioteki DLL lub EXE, nie ma wątpliwości, która wersja ma.
Ograniczenia interfejsu API
Niektóre funkcje MFC nie dotyczy wersji biblioteki DLL, ze względu na ograniczenia techniczne lub ponieważ te usługi są zazwyczaj świadczone przez aplikację.W bieżącej wersji usługi MFC, jedyną funkcją, która nie jest stosowana jest CWinApp::SetDialogBkColor.
Budowanie biblioteki DLL
Podczas kompilowania regularnych biblioteki dll, które statycznie do MFC, symbole _USRDLL i _WINDLL musi być zdefiniowana.Kod DLL musi być również skompilowana z następujące przełączniki kompilatora:
/D_WINDLLoznacza, że jest kompilacji dla biblioteki DLL
/D_USRDLLOkreśla, że tworzysz regularnych DLL
Należy także zdefiniować te symbole i używać tych przełączników kompilator podczas kompilowania regularnych biblioteki dll, które dynamicznie połączyć MFC.Dodatkowo, symbol _AFXDLL musi być zdefiniowana i kodzie DLL muszą być skompilowane z:
- /D_AFXDLLOkreśla budują regularnych biblioteki DLL, która dynamicznie łącza do biblioteki MFC
Interfejsy (API) między aplikacją i Biblioteka DLL muszą być jawnie eksportowane.Zaleca się zdefiniowanie interfejsów za mała przepustowość i używać tylko interfejsów C, jeżeli jest to możliwe.Interfejsy bezpośredniego C są łatwiejsze do utrzymania niż bardziej złożonych klasy języka C++.
Umieść swoje interfejsy API w oddzielny nagłówek, które mogą być zawarte przez pliki C i C++.Zobacz nagłówek ScreenCap.h w próbce MFC zaawansowane koncepcje DLLScreenCap na przykład.Aby eksportować swoje funkcje, należy wprowadzić je w EXPORTS sekcja pliku definicji modułu (.DEF) lub zawierać __declspec(dllexport) w swojej definicji funkcji.Użycie __declspec(dllimport) Aby zaimportować te funkcje do pliku wykonywalnego klienta.
Należy dodać AFX_MANAGE_STATE makro na początku eksportowanych funkcji w bibliotekach DLL regularnych, które dynamicznie połączyć MFC.To makro ustawia bieżący stan modułu na jednego dla biblioteki DLL.Na używanie tego makra, należy dodać następujący wiersz kodu na początek funkcji wyeksportowanych z biblioteki DLL:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
WinMain -> DllMain
Biblioteki MFC definiuje standardowy Win32 DllMain punkt wejścia, który inicjuje Twój CWinApp pochodnych obiektu jak typowa aplikacja MFC.Umieść wszystkie inicjalizacji specyficznej dla biblioteki DLL w InitInstance metody jak w typowych aplikacji MFC.
Należy zauważyć, że CWinApp::Run mechanizm nie ma zastosowania do biblioteki DLL, ponieważ aplikacja jest właścicielem pompy głównej wiadomości.Jeśli ma okno ramkę główną własnej biblioteki DLL lub wyświetla Niemodalne okna dialogowe, pompy głównej wiadomości aplikacji należy wywołać procedurę wyeksportowane biblioteki DLL, która wywołuje CWinApp::PreTranslateMessage.
Zobacz przykładowe DLLScreenCap korzystania z tej funkcji.
DllMain Funkcja pozwalająca MFC będzie wywoływać CWinApp::ExitInstance metody klasy, która jest pochodną CWinApp przed Biblioteka DLL jest zwalniana.
Łączenie biblioteki DLL
Z regularnych dll statycznie łączących się MFC możesz połączyć biblioteki DLL z Nafxcwd.lib lub Nafxcw.lib i z wersją środowiska wykonawczego C o nazwie Libcmt.lib.Biblioteki te są wstępnie zbudowane i może być zainstalowany przez wskazanie ich podczas uruchamiania Instalatora programu Visual C++.
Przykładowy kod
Zobacz przykładowy MFC zaawansowane koncepcje pakietu DLLScreenCap całą próbkę.Kilka ciekawych rzeczy pamiętać w tym przykładzie są następujące:
Flagi kompilatora biblioteki dll i tych aplikacji są różne.
Linie łączy i.DEF pliki dll i tych aplikacji są różne.
Aplikacja korzystająca z pliku DLL nie ma być w języku C++.
Interfejs między aplikacją i biblioteki DLL jest interfejs API, który może być używany w C lub C++ i są wywożone z DLLScreenCap.def.
Poniższy przykład ilustruje interfejs API, który jest zdefiniowany w regularnych biblioteki DLL, które statycznie łączy się MFC.W tym przykładzie deklaracji jest ujęty w extern "C" { } bloku dla użytkowników języka C++.Ma wiele zalet.Po pierwsze to sprawia, że Twój DLL interfejsów API użytkowej przez aplikacje klienckie-C++.Po drugie zmniejsza to obciążenie DLL, ponieważ przekręcona nazwa języka C++, nie zostaną zastosowane do nazwy eksportowanych.W końcu, ona ułatwia jawnie dodać do.DEF pliku (w przypadku wywozu przez porządkowe) bez martwienia się o przekręcona nazwa.
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct TracerData
{
BOOL bEnabled;
UINT flags;
};
BOOL PromptTraceFlags(TracerData FAR* lpData);
#ifdef __cplusplus
}
#endif
Struktura używana przez interfejs API są nie pochodzi od klasy MFC i są zdefiniowane w nagłówku API.Zmniejsza złożoność interfejs między biblioteki DLL i aplikacji i sprawia, że biblioteka DLL zdatny do użycia przez programy C.