TN011:作为DLL的一部分使用的MFC
此说明描述了规则 DLL 中,作为 windows 动态链接库的一部分,允许您使用 MFC 库 (DLL)。 假定,您熟悉 windows DLL 以及如何编译它们。 有关 MFC 扩展 DLL 的信息,可以创建扩展到 MFC 库,请参见 MFC 的 DLL 版本。
DLL 接口
普通 DLL 假定应用程序和 DLL 之间建立在与 C 函数或显式导出的类指定。 MFC 类接口不能导出。
如果 DLL 和应用程序中使用 MFC,则有一个替代使用 MFC 库的共享版本或对静态与库复制链接。 应用程序和 DLL 本身都使用一个 MFC 库的标准版本。
规则 DLL 具有以下优点:
使用 DLL 的应用程序不必使用 MFC,因此不必是 Visual C++ 应用程序。
与静态链接到 MFC 的规则 DLL, DLL 的范围仅依赖于使用和链接的 MFC 和 C 运行时实例。
与动态链接到 MFC 的规则 DLL,在内存使用共享 MFC 版本会节省大量的版本非常显着。 但是,您必须分配共享 DLL、 MFC<版本>.dll 和 Msvvcrt 用 DLL 的<版本>.dll,。
DLL 模型是独立类的实现方式。 您的 DLL 模型设置为所需的 API 只导出。 结果,因此,如果实现更改,规则 DLL 是有效的。
规则 DLL,因此,如果 DLL 和应用程序使用 MFC 静态链接到 MFC,不比 DLL 需要反之亦然 MFC 的不同版本或的应用程序的问题。 由于静态链接到 MFC 库为每个 DLL 或 EXE,没有关哪个版本的问题有。
API 限制
某些 MFC 功能不适用于 DLL 版本,或者由于技术限制或,因为应用程序通常提供这些服务。 MFC 的最新版本,不适用的唯一功能是 CWinApp::SetDialogBkColor。
生成 DLL
当必须定义生成规则 DLL 使用 MFC、符号 _USRDLL 和 _WINDLL 时静态链接。 还必须生成 DLL 代码与以下编译器开关:
/D_WINDLL 表示生成为 DLL
/D_USRDLL 指定要生成规则 DLL
,当您动态生成规则 DLL 链接到 MFC,则还必须定义这些符号和使用这些编译器开关。 此外,必须定义符号 _AFXDLL ,并且必须生成 DLL 代码为:
- /D_AFXDLL 指定要生成该 MFC 的规则 DLL 动态链接
必须显式接口导出 (API) 应用程序和 DLL 之间。 建议您定义了接口是低带宽,并仅使用 C 接口,则可以。 直接 C 接口比更复杂的 C++ 类易于维护。
将 API 在可由 C 和 C++ 文件中的一个单独的头。 有关示例参见 MFC 高级概念的示例 DLLScreenCap 的头 ScreenCap.h。 若要导出您的功能,输入它们在的模块定义文件 (.DEF) 的 EXPORTS 部分或包含在您定义的功能 __declspec(dllexport) 。 使用 __declspec(dllimport) 导入这些函数到客户端可执行文件。
必须在动态链接到 MFC 的规则 DLL 的所有导出的函数的开头添加 AFX_MANAGE_STATE 宏。 此宏将当前模块的状态为 DLL 的状态。 若要使用此宏,请将以下代码行添加到从 DLL 导出函数的开头:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
WinMain - > DllMain
MFC 库定义可初始化的 CWinApp 派生的对象在典型的 MFC 应用程序的标准 Win32 DllMain 入口点。 将所有 DLL 特定的初始化在 InitInstance 方法在典型的 MFC 应用程序。
请注意,CWinApp::Run 机制不适用于 DLL,因为应用程序拥有主消息泵。 如果 DLL 显示无模式对话框或有自己的主框架窗口,则应用程序的主消息泵必须调用 CWinApp::PreTranslateMessage的 DLL 导出的例程。
请参见 DLLScreenCap 示例有关此功能的使用。
MFC 提供的 DllMain 函数将调用从 CWinApp派生您的类的 CWinApp::ExitInstance 方法,在卸载 DLL 之前
链接到的 DLL
与静态链接到 MFC 的规则 DLL,必须链接到的 DLL 与 Nafxcwd.lib 或 Nafxcw.lib 和使用名为 Libcmt.lib 的 C 运行时的版本。 这些库是预建,并可通过指定其安装,当运行 Visual C++ 设置。
代码示例
请参见完整示例的 MFC 高级概念 DLLScreenCap 示例程序。 请注意几个有趣的内容本示例如下:
DLL 的编译器标志和这些应用程序是不同的。
链接线和 .DEF 文件的 DLL 以及这些应用程序的不同。
使用 DLL 的应用程序不必在 C++。
应用程序和由 C 或 C++ 可用和导出与 DLLScreenCap.def 的 DLL 之间的接口是 API。
在该的规则 DLL 定义与静态链接到 MFC 的下面的示例阐释了 API。 在此示例中,声明在 extern "C" { } 将对 C++ 用户块。 这有若干优点。 首先,它使 DLL API 可由非 C++ 客户端应用程序。 接下来,,因为 C++ 名称重整不适用于导出的名称,因此它减少 DLL 系统开销。 最后,这样做更易于显式添加到 .DEF 文件 (用于导出序号),而无需担心名称重整。
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct TracerData
{
BOOL bEnabled;
UINT flags;
};
BOOL PromptTraceFlags(TracerData FAR* lpData);
#ifdef __cplusplus
}
#endif
API 使用的结构与 MFC 类在 API 头尚未派生并定义。 这将减少接口的复杂 DLL 和应用程序之间的并使 DLL 可由 C 程序。