博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

VC 宏AFX_EXT_CLASS 【转】

Posted on 2013-06-12 22:49  泡泡糖  阅读(633)  评论(0编辑  收藏  举报

原文: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。

注意   如果导出整个类而非选定的类成员,静态数据成员将自动导出。