动态库导出符号与extern “C“

发布于:2025-06-04 ⋅ 阅读:(22) ⋅ 点赞:(0)

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 文件时,会根据头文件声明自动应用导出规则,无需在实现中重复指定。


网站公告

今日签到

点亮在社区的每一天
去签到