原文:http://xinbaojiang.blog.163.com/blog/static/119970729200952411266197/
使用 AFX_EXT_CLASS 导出和导入
扩展DLL使用 AFX_EXT_CLASS 宏导出类;链接到扩展 DLL 的可执行文件使用该宏导入类。使用 AFX_EXT_CLASS 宏,用于生成扩展 DLL 的相同头文件可以与链接到 DLL 的可执行文件一起使用。
在 DLL 的头文件中,将 AFX_EXT_CLASS 关键字添加到类的声明中,如下所示:
class AFX_EXT_CLASS CMyClass : public Cdocument {// };
当定义了预处理 _AFXDLL 和 _AFXEXT 时,该宏被 MFC 定义为 __declsp(dllexport).但当定义了 _AFXDLL 而未定义 _AFXEXT 时,该宏被定义为 __declspec(dllimport)。定义后,预处理器符号 _AFXDLL 指示共享 MFC 版本正在由目标可执行文件(DLL 或应用程序)使用。当 _AFXDLL 和 _AFXEXT 都定义了时,这指示目标可执行文件是扩展 DLL。
由于从扩展 DLL 导出时,AFX_EXT_CLASS 被定义为 __declspec(dllexport),因此可以导出整个类,而不必将该类的所有符号的修饰名放到 .DEF 文件中。此方法由 MFC 示例 DLLHUSK 使用。
虽然使用此方法可以避免创建 .DEF 文件和类的所有修饰名,但由于名称可以按序号导出,创建 .DEF 文件的效率更高。若要使用 .DEF 文件导出方法,请将下列代码放在头文件的开头和结尾处:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
//
#undef AFX_DATA
#define AFX_DATA
警告 导出内联函数时要小心,因为它们有可能导致版本冲突。内联函数扩展到应用程序代码中;因此,如果以后重写内联函数,除非重新编译应用程序本身,否则内联函数不会被更新。(通常,不用重新生成使用 DLL 函数的应用程序就可以更新 DLL 函数。)
导出类中的个别成员
有时,您可能希望导出类中的个别成员。例如,如果导出 CDialog 派生类,可能只需要导出构造函数和 DoModal 调用。可以对需要导出的个别成员使用 AFX_EXT_CLASS。
例如:
class CExampleDialog : public CDialog
{
public:
AFX_EXT_CLASS CExampleDialog();
AFX_EXT_CLASS int DoModal();
...
// rest of class definition
...
};
您不再导出类的所有成员,但由于 MFC 宏的工作方式,您可能会遇到其他问题。几个 MFC 的 Helper 宏实际声明或定义数据成员。因此,还必须从 DLL 导出这些数据成员。
例如,当生成扩展 DLL 时,DECLARE_DYNAMIC 宏的定义如下:
#define DECLARE_DYNAMIC(class_name)
protected:
static CRuntimeClass* PASCAL _GetBaseClass();
public:
static AFX_DATA CRuntimeClass class##class_name;
virtual CRuntimeClass* GetRuntimeClass() const;
以 static AFX_DATA 打头的行声明类的内部静态对象。若要正确导出该类并从客户端可执行文件访问运行时信息,必须导出此静态对象。由于静态对象是用 AFX_DATA 修饰符声明的,因此只需在生成 DLL 时将 AFX_DATA 定义为 __declspec(dllexport),并在生成客户端可执行文件时将 AFX_DATA 定义为 __declspec(dllimport)。由于已经以此方式定义了 AFX_EXT_CLASS,因此只需参考类定义,将 AFX_DATA 重定义为与 AFX_EXT_CLASS 相同。
例如:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_CLASS
class CExampleView : public CView
{
DECLARE_DYNAMIC()
// ... class definition ...
};
#undef AFX_DATA
#define AFX_DATA
MFC 总是在其宏的内部定义的数据项上使用 AFX_DATA 符号,因此该技术适用于所有这类情况。例如,它适用于 DECLARE_MESSAGE_MAP。
注意 如果导出整个类而非选定的类成员,静态数据成员将自动导出。