1. windows下动态库导出符号
根据C/C++语法规则,函数声明中的修饰符(如__declspec(dllexport))可以放在返回类型之前或返回类型之后、函数名之前。这两种方式在功能上是等价的,编译器会以相同的方式处理。
__declspec(dllexport) int MyGlobalFunc(int a, int b);
int __declspec(dllexport) MyGlobalFunc(int a, int b);
注:
声明函数/类的 签名和导出属性(如 extern “C” 或 __declspec(dllexport)),告知编译器按特定规则生成符号名。编译器在处理 CPP 文件时,会根据头文件声明自动应用导出规则,无需在实现中重复指定。
2. linux下动态库导出符号
Linux 系统中导出动态库(通常称为共享对象 .so 文件)不需要使用 __declspec(dllexport)。这是 Linux 与 Windows 动态链接机制的核心区别,主要原因如下:
Linux下,动态库符号默认全局可见性,Linux 的动态库(.so)基于 ELF(Executable and Linkable Format)格式,默认导出所有全局函数和变量(除非显式隐藏。无需额外声明导出修饰符(如 Windows 的 __declspec(dllexport)),编译器会直接导出符号。
linux下有个符号隐藏控制,可以控制符号的可见性,即使用 GCC 的编译选项 -fvisibility=hidden,隐藏所有未显式标记的符号。通过 attribute((visibility(“default”))) 显式导出目标函数/类,例如:
// 显式导出函数
__attribute__((visibility("default"))) void my_exported_func();
3. extern "C"修饰符
c++代码使用,强制导出符号按c语言的规则,即不改写函数名,一般有两种写法,
-
批量修饰
#ifdef __cplusplus extern "C" { #endif __declspec(dllexport) int MyGlobalFunc1(int a, int b); __declspec(dllexport) int MyGlobalFunc2(int a, int b); //略... #ifdef __cplusplus } #endif
-
单个修饰(简化下,就省略了#ifdef __cplusplus,因为均是c++项目,上面是演示下如何使用宏去正确使用extern “C”)
extern "C" __declspec(dllexport) int MyGlobalFunc(int a, int b);
注:
声明函数/类的 签名和导出属性(如 extern “C” 或 __declspec(dllexport)),告知编译器按特定规则生成符号名。编译器在处理 CPP 文件时,会根据头文件声明自动应用导出规则,无需在实现中重复指定。