Ben*_*min 9 windows dll dllimport dllexport visual-studio
DLL导出标题
extern "C"
void _declspec(dllexport) __stdcall foo();
Run Code Online (Sandbox Code Playgroud)
.def文件
EXPORTS
foo @1
Run Code Online (Sandbox Code Playgroud)
当我通过64位构建配置构建dll时,我遇到了这个警告.
警告LNK4197:多次指定导出'foo'; 使用第一个规范
但是,如果我通过32位构建配置构建dll,则警告永远不会发生.
问题是什么?有什么不同.
在接口的dll头文件中,我们通常使用这个技术,
#ifdef EXPORT_DLL
#define BASICAPI _declspec(dllexport)
#else
#define BASICAPI _declspec(dllimport)
#endif //_EXPORT_DLL
Run Code Online (Sandbox Code Playgroud)
但是如果def文件也存在,我们总是会在构建64位dll时遇到警告.
那么,我们应该写这样的代码吗?
#ifdef EXPORT_DLL
#define BASICAPI
#else
#define BASICAPI _declspec(dllimport)
#endif //_EXPORT_DLL
Run Code Online (Sandbox Code Playgroud)
它运作良好.但这对我来说并不熟悉.
给我你的意见.
Dea*_*ing 11
对同一函数指定两次导出通常不是好的做法.如果您已经拥有,__declspec(dllexport)那么您也不需要在.def文件中指定导出.相反,如果您在.def文件中列出了导出,那么就不需要了__declspec(dllexport).
我相信警告的原因是在x86版本中,__declspec(dllexport)使用前导下划线导出装饰名称,但64位编译器不会使用前导下划线装饰名称,从而导致重复.要验证这一点,您可以查看Dependency Walker中的32位DLL,您应该看到两个导出函数"foo"和"_foo".
__declspec(dllexport)和.def文件是从dll导出符号的两种不同方法.你不需要两者,应该省略它们.该__declspec方法对于c ++程序来说功能更为通用,因为它使用c ++ mangling导出名称,允许导出重载函数,但相反,这会使名称更难通过GetProcAddress导入.
此外,使用类似的通用宏EXPORT_DLL是危险的,因为它意味着您无法构建一个使用另一个dll的dll,而没有一个dll尝试导出两个dll的所有符号.
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);
Run Code Online (Sandbox Code Playgroud)
功能1和2可与GetProcAddress的被得到作为_Function1@0和Function2分别.Function3将通过编译器特定的受损名称导出,类似于:@Function3@@UAG_DB@Z.该名称对于函数的每个重载都是不同的,这是它允许重载工作的方式.
重要的是要知道__declspec.def文件的名称错误并不关心,只会导出Function1,Function2和Function3.
| 归档时间: |
|
| 查看次数: |
3831 次 |
| 最近记录: |