Sdílet prostřednictvím


TN011: Použití prostředí MFC jako součásti knihovny DLL

Tato poznámka popisuje běžné knihovny MFC DLL, které umožňují používat knihovnu MFC jako součást knihovny DLL (Dynamic Link Library). Předpokládá se, že znáte knihovny DLL systému Windows a jak je sestavit. Informace o knihovnách DLL rozšíření MFC, pomocí kterých můžete vytvořit rozšíření knihovny MFC, naleznete v tématu Verze knihovny MFC knihovny DLL.

Rozhraní DLL

běžné knihovny MFC DLL předpokládají, že rozhraní mezi aplikací a knihovnou DLL jsou specifikována ve funkcích podobných jazyku C nebo explicitně exportovaných tříd. Rozhraní tříd MFC nelze exportovat.

Pokud knihovna DLL i aplikace chtějí používat knihovnu MFC, obě mají možnost použít buď sdílenou verzi knihoven MFC, nebo staticky propojit kopii knihoven. Aplikace i knihovna DLL mohou používat jednu ze standardních verzí knihovny MFC.

běžné knihovny MFC DLL mají několik výhod:

  • Aplikace, která používá knihovnu DLL, nemusí používat mfc a nemusí být aplikací Visual C++.

  • U běžných knihoven MFC DLL, které staticky propojují s mfc, závisí velikost knihovny DLL pouze na rutinách modulu runtime MFC a C, které se používají a propojují.

  • S běžnými knihovnami MFC DLL, které dynamicky propojuje s mfc, mohou být úspory v paměti při použití sdílené verze knihovny MFC významné. Musíte však distribuovat sdílené knihovny DLL, mfc<version.dll> a Msvvcrt<version.dll> s knihovnou DLL.

  • Návrh knihovny DLL je nezávislý na způsobu implementace tříd. Návrh knihovny DLL exportuje pouze do požadovaných rozhraní API. V důsledku toho platí, že pokud se implementace změní, jsou běžné knihovny MFC DLL stále platné.

  • S běžnými knihovnami MFC DLL, které staticky propojují s knihovnou MFC, pokud knihovna DLL i aplikace používají mfc, neexistují žádné problémy s aplikací, která chce jinou verzi knihovny MFC než knihovna DLL nebo naopak. Vzhledem k tomu, že knihovna MFC je staticky propojena s každou knihovnou DLL nebo EXE, není pochyb o tom, jakou verzi máte.

Omezení rozhraní API

Některé funkce MFC se nevztahují na verzi knihovny DLL, a to buď z důvodu technických omezení, nebo proto, že tyto služby jsou obvykle poskytovány aplikací. S aktuální verzí knihovny MFC je jedinou funkcí, která není použitelná CWinApp::SetDialogBkColor.

Sestavení knihovny DLL

Při kompilaci běžných knihoven MFC DLL, které staticky propojují s MFC, musí být definovány symboly a _WINDLL musí být definovány_USRDLL. Kód knihovny DLL musí být také zkompilován pomocí následujících přepínačů kompilátoru:

  • /D_WINDLL označuje kompilaci pro knihovnu DLL.

  • /D_USRDLL určuje, že vytváříte běžnou knihovnu MFC DLL.

Tyto symboly musíte také definovat a použít tyto přepínače kompilátoru při kompilaci běžných knihoven MFC DLL, které dynamicky propojují s mfc. Kromě toho musí být symbol _AFXDLL definován a kód knihovny DLL musí být zkompilován pomocí:

  • /D_AFXDLL určuje, že vytváříte běžnou knihovnu MFC DLL, která dynamicky propojuje knihovnu MFC.

Rozhraní (API) mezi aplikací a knihovnou DLL musí být explicitně exportována. Doporučujeme definovat rozhraní tak, aby byla nízká šířka pásma, a pokud je to možné, používejte pouze rozhraní jazyka C. Přímé rozhraní jazyka C jsou snadnější udržovat než složitější třídy jazyka C++.

Umístěte rozhraní API do samostatné hlavičky, kterou můžou zahrnout soubory C i C++. Příklad najdete v hlavičce ScreenCap.h v ukázce DLLScreenCap knihovny MFC Advanced Concepts. Pokud chcete exportovat funkce, zadejte je do EXPORTS části definičního souboru modulu (. DEF) nebo zahrnout do __declspec(dllexport) definic funkcí. Slouží __declspec(dllimport) k importu těchto funkcí do spustitelného souboru klienta.

Na začátek všech exportovaných funkcí je nutné přidat makro AFX_MANAGE_STATE v běžných knihovnách MFC DLL, které dynamicky propojují s mfc. Toto makro nastaví aktuální stav modulu na aktuální modul pro knihovnu DLL. Chcete-li použít toto makro, přidejte následující řádek kódu na začátek funkcí exportovaných z knihovny DLL:

AFX_MANAGE_STATE(AfxGetStaticModuleState( ))

WinMain –> DllMain

Knihovna MFC definuje standardní vstupní bod Win32 DllMain , který inicializuje odvozený objekt CWinApp jako v typické aplikaci MFC. Všechny inicializace specifické pro knihovnu DLL umístěte do metody InitInstance jako v typické aplikaci MFC.

Všimněte si, že mechanismus CWinApp::Run se nevztahuje na knihovnu DLL, protože aplikace vlastní hlavní čerpadlo zpráv. Pokud knihovna DLL zobrazuje bezmodální dialogy nebo má vlastní okno hlavního rámce, hlavní zpráva pumpa vaší aplikace musí volat dll exportovanou rutinu, která volá CWinApp::P reTranslateMessage.

Podívejte se na ukázku DLLScreenCap pro použití této funkce.

Funkce DllMain , kterou knihovna MFC poskytuje, bude volat CWinApp::ExitInstance metody vaší třídy, která je odvozena z CWinApp dříve, než je knihovna DLL uvolněna.

Propojení knihovny DLL

S běžnými knihovnami MFC DLL, které staticky odkazují na MFC, je nutné propojit knihovnu DLL s nafxcwd.lib nebo Nafxcw.lib a s verzí modulů runtime jazyka C s názvem Libcmt.lib. Tyto knihovny jsou předem sestavené a mohou být nainstalovány zadáním při spuštění instalačního programu Visual C++.

Ukázkový kód

Kompletní ukázku naleznete v ukázkovém programu MFC Advanced Concepts DLLScreenCap. Několik zajímavých věcí, které je třeba v této ukázce poznamenat, jsou následující:

  • Příznaky kompilátoru knihovny DLL a ty aplikace se liší.

  • Linkové čáry a . Def soubory pro knihovnu DLL a soubory pro aplikaci se liší.

  • Aplikace, která používá knihovnu DLL, nemusí být v jazyce C++.

  • Rozhraní mezi aplikací a knihovnou DLL je rozhraní API, které lze použít jazykem C nebo C++ a je exportováno pomocí knihovny DLLScreenCap.def.

Následující příklad znázorňuje rozhraní API definované v běžné knihovně MFC DLL, která staticky odkazuje na knihovnu MFC. V tomto příkladu je deklarace uzavřena v extern "C" { } bloku pro uživatele jazyka C++. To má několik výhod. Za prvé, vaše rozhraní DLL API použitelné klientskými aplikacemi, které nejsou C++. Za druhé snižuje režii knihovny DLL, protože pro exportovaný název se nepoužije mangling názvu jazyka C++. A konečně, usnadňuje explicitní přidání do souboru . Def soubor (pro export podle řad) bez obav o mangling názvů.

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

struct TracerData
{
    BOOL bEnabled;
    UINT flags;
};

BOOL PromptTraceFlags(TracerData FAR* lpData);

#ifdef __cplusplus
}
#endif

Struktury používané rozhraním API nejsou odvozeny z tříd MFC a jsou definovány v hlavičce rozhraní API. Tím se snižuje složitost rozhraní mezi knihovnou DLL a aplikací a zpřístupňuje knihovnu DLL programy jazyka C.

Viz také

Technické poznámky podle čísel
Technické poznámky podle kategorií