DLL导出符号注意事项
2024-03-17 17:33:41

导出DLL函数有两种方法:

  1. 使用 __declspec(dllexport) 语法。
  2. 使用 .def 文件。

但两者是有区别的,比如有这样一个函数签名
int __stdcall Foo(int);

方法 lib符号名称 dll导出名称
__declspec(dllexport) ?Foo@@YGHH@Z ?Foo@@YGHH@Z
.def file ?Foo@@YGHH@Z Foo

.def文件导出的函数名称是干净的,也方便其他程序调用。
__declspec(dllexport)导出的名称被修饰了,只适合C++程序使用。

extern “C”

extern "C"的主要目的就是抑制C++编译器修饰符号名称,比如将 Foo 函数签名修改如下
extern "C" __declspec(dllexport) int __stdcall Foo(int);
导出符号变为:

方法 lib符号名称 dll导出名称
__declspec(dllexport) _Foo@4 _Foo@4
.def file _Foo@4 Foo

总结

  • 对于 lib 静态库,用 __declspec(dllexport) 导出,用 __declspec(dllimport) 导入。不需要extern "C"
  • 对于 dll 动态库,如果需要供非C++程序使用,用.def文件声明导出函数,而不是__declspec(dllexport)
  • 在导出 dll 函数时,EXTERN_C虽然不是必须的,但是建议加上,可供C语言调用。

相关阅读

how does extern “C” allow C++ code in a C file?
Importing and Exporting
Viewing Decorated Names
GCC and MSVC C++ Demangler