关于不一致的dll链接

50
我应该如何移除这个链接警告?你可以查看导致这个警告的代码段。
static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
//bla bla
// Exported DLL initialization is run in context of running application
    extern "C" void WINAPI InitGuiCtrlsDLL()
    {
     // create a new CDynLinkLibrary for this app
      new CDynLinkLibrary(GuiCtrlsDLL);
     // nothing more to do
    }

警告 C4273: 'InitGuiCtrlsDLL' : 不一致的 DLL 链接

我还有导出和导入的定义,如:

#ifdef _GUICTRLS
   #define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
   #define GUI_CTRLS_EXPORT  __declspec(dllimport)
#endif
8个回答

57

预处理器语句的目的:

#ifdef _GUICTRLS 
   #define GUI_CTRLS_EXPORT __declspec(dllexport) 
#else 
   #define GUI_CTRLS_EXPORT  __declspec(dllimport) 
#endif 

需要确保在定义类或函数的.dll文件中,头文件声明该类或函数为__declspec(dllexport),在任何其他可能使用它的.dll文件中则声明为__declspec(dllimport)。

为了使此工作正常,必须在编译导出的.dll文件时定义_GUICTRLS,而对于任何其他.dll文件,则不应定义。通常,您可以在项目属性下的C/C++ -> Preprocessor -> Preprocessor Definitions中预期会定义_GUICTRLS。

您看到的编译器错误通常是因为未为执行导出的项目定义_GUICTRLS,或者在多个项目中定义了它,通常是从一个项目中剪切并粘贴到另一个项目中导致的。如果在多个项目中包含一个定义了_GUICTRLS的头文件,则也会看到此错误。


28
有多种可能性:
1)static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL }; 你使用了AFX_EXTENSION_MODULE。这意味着你正在实现一个MFC扩展DLL。对于这样的扩展dll,你必须定义预处理器_AFXEXT。在Visual C++项目的C++编译器设置中设置它。
参见:
如何在MFC扩展DLL中使用_declspec(dllexport): http://support.microsoft.com/kb/128199 AFX_EXTENSION_MODULE结构: http://msdn.microsoft.com/en-us/library/sxfyk0zk.aspx TN033:MFC的DLL版本: http://msdn.microsoft.com/en-us/library/hw85e4bb.aspx 2)很可能是您有重复的定义/声明。

1
帮助我找到了一个缺失的DLL_EXPORT,该错误显示相同。 - fiorentinoing

4
除了阅读警告消息之外,如果您的工作区包含多个项目,请注意它出现在哪里。如果您的工作区包含多个项目,则需要特别注意。
我浪费了时间在查找我的DLL中的问题,尽管编译和链接都正确。工作区也在构建主应用程序,而我的错误在于不小心将一个新的(DLL)源文件包含到应用程序本身的构建文件列表中。
主程序需要DLL头文件mynewdll.h来导入东西,但不需要源文件mynewdll.cpp。(代码在运行时通过DLL引入。)我有一个习惯,就是将头文件和代码文件作为一对包含在项目中,这就是我犯错的地方。
如果我当时警觉并注意到DLL项目没有错误链接,而是主程序抱怨了,我本可以更早地发现错误!
我的DLL源代码和项目没有错误,只是我尝试构建可执行文件的方式有误。

3
那个警告通常是由于函数的重复定义,在使用dllimport时有所不同。您确定没有这样做吗?

@Matteo 我已经检查了源代码,没有重复的部分。 - baris.aydinoz

2

[CMake 不一致的 DLL 链接]

我遇到了以下问题和解决方案,涉及 __declspec(dllexport) 和 __declspec(dllimport):

# # #CMakeLists.txt
add_defintions(-DMYLIB=1)
# The above was the solution...
#    (MYLIB is used in the standard ifdef + define MYLIB_EXPORT syntax)
#  Below: seems to get overruled by other directory's headers: 
set_source_files_properties(  file1.h  file2.h  COMPILE_FLAGS "-DMYLIB=1") 

这很让人烦恼,因为很多资料都说要使用“设置源文件属性”命令来获得更好的细粒度,但文档没有明确说明当从不同目录包含file1.h的声明时会发生什么...最好现在还是坚持使用add_definitions(-DMYLIB=1)

为了捕捉这个问题:在你的Foo.cpp文件中:

#include "export.h"
#if defined(MYLIB)
#if defined(OTHERLIB)
  static_assert(0,"error, check your definitions!");
  // OTHER depends on MY; can't have both of these flags being set!
#endif
#endif
struct  OTHER_EXPORT  foo 
{ 
};

1

请确保您没有在不同的项目中定义导出的符号。同时手动清除所有中间文件并重新编译。


0
为了进一步阐述damian的答案,我读了它,但一开始并没有理解。
你有一个包含函数的源文件编译后形成的共享库。在一个新项目中,你使用了这个库,并且还编译了源文件以使用该函数(我忘记了它已经在库中)。在库中,函数的标签被导出,在额外编译的源文件中,函数的标签被标记为导入。这就是冲突所在。

-1
在我的情况下,错误C4273是由于尝试从Qt5中的msvc2017_64工具链动态加载测试应用程序链接到.lib文件导致的。通过在.pro文件中更改LIBS设置以删除对.lib文件的引用,问题得到解决。

非常费解 - Ingo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接