构建64位dll的警告

时间:2010-08-26 05:46:44

标签: windows visual-studio dll dllimport dllexport

dll导出标题

extern "C"
void _declspec(dllexport) __stdcall foo();

.def文件

EXPORTS
foo         @1

当我通过64位构建配置构建dll时,我遇到了这个警告。

  

警告LNK4197:多次指定导出'foo';使用第一个规范

但如果我通过32位构建配置构建dll,则不会发出警告 问题是什么?有什么区别。

在接口的dll标头中,我们通常使用这个技术,

#ifdef EXPORT_DLL
#define BASICAPI _declspec(dllexport)
#else
#define BASICAPI _declspec(dllimport)
#endif //_EXPORT_DLL

但是如果def文件也存在,我们总是会在建立64bit dll时遇到警告 那么,我们应该写这样的代码吗?

#ifdef EXPORT_DLL
#define BASICAPI
#else
#define BASICAPI _declspec(dllimport)
#endif //_EXPORT_DLL

效果很好。但这对我来说并不熟悉 给我你的意见。

2 个答案:

答案 0 :(得分:11)

为同一个函数指定两次导出通常不是好的做法。如果您已经有__declspec(dllexport),那么您也不需要在.def文件中指定导出。相反,如果您在.def文件中列出了导出,那么就不需要__declspec(dllexport)

我认为警告的原因是在x86版本中,__declspec(dllexport)正在使用前导下划线导出装饰名称,但64位编译器不会使用前导下划线装饰名称,导致重复。要验证这一点,你可以查看Dependency Walker中的32位DLL,你应该看到两个导出的函数,“foo”和“_foo”。

答案 1 :(得分:5)

__declspec(dllexport)和.def文件是两种不同方式从dll导出符号。你不需要两者,应该省略它们。 {c}程序的__declspec方法通用性更强,因为它使用c ++修改导出名称,允许导出重载函数,但相反,这会使名称更难通过GetProcAddress导入。

此外,使用像EXPORT_DLL这样的通用宏是危险的,因为它意味着你无法构建一个使用另一个dll的dll,而没有一个dll试图导出两个dll的所有符号。 / p>

DevStudio会自动在dll项目上创建一个符号:<PROJECT>_EXPORTS使创建EXPORT宏变得简单而安全:

#ifdef EXPORT
#undef EXPORT
#endif
#ifdef PROJECTNAMEHERE_EXPORTS
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

EXTERN_C EXPORT void __stdcall Function1(void);
EXTERN_C EXPORT void __cdecl Function2(...);
         EXPORT void Function3(void);

功能1&amp;可以使用GetProcAddress分别获得2 _Function1@0Function2。 Function3将通过编译器特定的受损名称导出,其名称类似于:@Function3@@UAG_DB@Z。这个名称对于函数的每个重载都是不同的,这就是它允许重载工作的方式。

了解__declspec名称为.def文件的名称并不重要,只需要导出Function1Function2Function3