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
效果很好。但这对我来说并不熟悉 给我你的意见。
答案 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@0
和Function2
。 Function3将通过编译器特定的受损名称导出,其名称类似于:@Function3@@UAG_DB@Z
。这个名称对于函数的每个重载都是不同的,这就是它允许重载工作的方式。
了解__declspec
名称为.def文件的名称并不重要,只需要导出Function1
,Function2
和Function3
。