扩展DLL调用扩展DLL的LINK2001错误的解决办法之一

MFC通过_AFXEXT来决定AFX_EXT_CLASS等宏应编译为导出还是导入。扩展DLL的项目预定义有_AFXEXT宏,因此,AFX_EXT_CLASS被编译为导出类;非扩展DLL项目不带有_AFXEXT宏,因此, AFX_EXT_CLASS被编译出导入类。同一个文件中的符号在不同的工程被编译为不同的涵义,这就是使用扩展DLL的项目中能够直接使用扩展DLL定义的头文件的原因。

问题则是,当一个扩展DLL要使用另一个扩展DLL时,由于本项目也有_AFXEXT预定义宏,因此,被引用DLL的头文件中的AFX_EXT_CLASS不能如预期那样编译为导入类,而是导出类。由于本项目中并未定义有被引用DLL中的类,因此将出现LINK2001错误。

已经的解决此问题的一个方法是在include被引用DLL的头文件前重定义AFX_EXT_CLASS宏。如下:

#undef AFX_EXT_CLASS
#undef AFX_EXT_API
#undef AFX_EXT_DATA
#define AFX_EXT_CLASS AFX_CLASS_IMPORT
#define AFX_EXT_API AFX_API_IMPORT
#define AFX_EXT_DATA AFX_DATA_IMPORT
//包含被调用MFC扩展DLL的头文件 #include "CalledDLL.h"
//恢复宏的含义为输出 #undef AFX_EXT_CLASS #undef AFX_EXT_API #undef AFX_EXT_DATA #define AFX_EXT_CLASS AFX_CLASS_EXPORT #define AFX_EXT_API AFX_API_EXPORT #define AFX_EXT_DATA AFX_DATA_EXPORT

若使用这个方法,所有引用该头文件的地方都必须加以这样的处理。我不喜欢这样的解决方案。

显然,若MFC通过_AFXEXT来决定AFX_EXT_CLASS在扩展DLL项目和非扩展DLL项目中的涵义,那么,我们也可以通过其它的标识符来使AFX_EXT_CLASS在源工程(生成该DLL的工程)和其它工程中具有不同的涵义。如果我们使用一个源工程中独有的宏来代替_AFXEXT,就可以保证头文件能够在所有其它工程中都能正确的编译为导入符号。

我们可以生成一个GUID来作为工程独一无二的宏,为了更有描述力,可以与项目名称组合到一起。假定我们定义了这样一个项目标识宏:

__ASYNCSOCKETCOMPONENT_8E324259_800C_4079_A147_48E8882AB2C0

则可以这样定义头文件:

#undef AFX_EXT_CLASS
#undef AFX_EXT_DATA
#undef AFX_EXT_API

#ifdef __ASYNCSOCKETCOMPONENT_8E324259_800C_4079_A147_48E8882AB2C0
    #define AFX_EXT_CLASS    AFX_CLASS_EXPORT
    #define AFX_EXT_DATA    AFX_DATA_EXPORT
    #define AFX_EXT_API        AFX_API_EXPORT
#else
    #define AFX_EXT_CLASS    AFX_CLASS_IMPORT
    #define AFX_EXT_DATA    AFX_DATA_IMPORT
    #define AFX_EXT_API        AFX_API_IMPORT
#endif

// 头文件内容

#undef AFX_EXT_CLASS
#undef AFX_EXT_DATA
#undef AFX_EXT_API

#ifndef AFX_EXT_DATA
    #ifdef _AFXEXT
        #define AFX_EXT_CLASS       AFX_CLASS_EXPORT
        #define AFX_EXT_API         AFX_API_EXPORT
        #define AFX_EXT_DATA        AFX_DATA_EXPORT
        #define AFX_EXT_DATADEF
    #else
        #define AFX_EXT_CLASS       AFX_CLASS_IMPORT
        #define AFX_EXT_API         AFX_API_IMPORT
        #define AFX_EXT_DATA        AFX_DATA_IMPORT
        #define AFX_EXT_DATADEF
    #endif
#endif

项目标识宏可以加到项目的预定义宏列表中。另外也可以加到stdafx.h中,再在头文件中添加对stdafx.h的引用。无论是Visual C还是C Builder,stdafx.h都是大部分类型的项目的标准文件,所以不用担心在其它项目中无法编译过去。

原文地址:https://www.cnblogs.com/yedaoq/p/1818137.html