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 程序。

请参见

其他资源

由Number "技术说明

技术说明按类别