C++标准库头文件 dlfcn.h 举例说明
C++标准库头文件 dlfcn.h 举例说明
1. <dlfcn.h>
<dlfcn.h>是 C 标准库中用于 动态加载共享库(Dynamic Loading) 的头文件,主要用于在运行时加载共享库(如 .so 文件或 .dll 文件),获取符号地址并调用其中的函数。以下是其核心函数和代码示例:
1. 核心函数
| 函数 | 说明 |
|---|---|
| dlopen | 打开共享库文件,返回句柄 |
| dlsym | 从共享库中获取符号(函数/变量)地址 |
| dlclose | 关闭共享库 |
| dlerror | 获取最近一次 dl 函数的错误信息 |
2. 代码示例
(1)动态加载共享库并调用函数
假设有一个共享库 libmath.so(Linux)或 math.dll(Windows),其中包含一个函数 int add(int a, int b)。
math.c(编译为共享库)
// 编译命令(Linux): gcc -shared -fPIC -o libmath.so math.c
// Windows(MinGW): gcc -shared -o math.dll math.c
int add(int a, int b) {
return a + b;
}
main.c(动态加载 libmath.so 并调用 add 函数)
#include <stdio.h>
#include <dlfcn.h> // Linux/macOS
// Windows 需用 `LoadLibrary`/`GetProcAddress`(见后文对比)
int main() {
void *handle; // 共享库句柄
int (*add_func)(int, int); // 函数指针
// 1. 加载共享库
handle = dlopen("./libmath.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "Error: %s\n", dlerror());
return 1;
}
// 2. 获取函数地址
add_func = (int (*)(int, int)) dlsym(handle, "add");
if (!add_func) {
fprintf(stderr, "Error: %s\n", dlerror());
dlclose(handle);
return 1;
}
// 3. 调用动态加载的函数
int result = add_func(3, 4);
printf("3 + 4 = %d\n", result);
// 4. 关闭共享库
dlclose(handle);
return 0;
}
编译并运行(Linux/macOS):
gcc -o main main.c -ldl # 链接 libdl 库
./main
==============================================
3 + 4 = 7
(2)Windows 下的动态加载(对比)
Windows 使用 <windows.h> 中的 LoadLibrary/GetProcAddress,而非 <dlfcn.h>:
#include <stdio.h>
#include <windows.h>
int main() {
HINSTANCE handle = LoadLibrary("math.dll");
if (!handle) {
fprintf(stderr, "Failed to load DLL\n");
return 1;
}
// 获取函数地址
int (*add_func)(int, int) = (int (*)(int, int)) GetProcAddress(handle, "add");
if (!add_func) {
fprintf(stderr, "Failed to find function\n");
FreeLibrary(handle);
return 1;
}
int result = add_func(3, 4);
printf("3 + 4 = %d\n", result);
FreeLibrary(handle);
return 0;
}
3. 关键点
(1)dlopen 模式
| 模式 | 说明 |
|---|---|
| RTLD_LAZY | 懒加载(首次调用时解析符号) |
| RTLD_NOW | 立即加载(返回前解析所有符号) |
| RTLD_GLOBAL | 符号可被后续加载的库使用 |
| RTLD_LOCAL | 符号仅当前库可见(默认) |
(2)dlsym 查找符号
- 可以查找 函数 或 全局变量 的地址。
- 返回 void*,需强制转换为正确的函数指针类型。
(3)错误处理
- dlerror() 返回最近一次 dl* 函数的错误信息(字符串)。
- 如果 dlopen/dlsym 失败,应检查 dlerror()。
4. 典型应用场景
插件系统
- 程序运行时加载插件(如浏览器插件、游戏模组)。
模块化设计
- 动态加载可选功能模块(如数据库驱动)。
热更新
- 不重启程序,替换共享库以实现更新。
5. 注意事项
-
跨平台兼容性
Linux/macOS 用 <dlfcn.h>,Windows 用 LoadLibrary/GetProcAddress。 -
名称修饰(C++)
C++ 函数名会编译成修饰名(如 _Z3addii),需用 extern "C" 避免:
extern "C" {
int add(int a, int b) { return a + b; }
}
- 内存泄漏
确保 dlclose 关闭不再使用的库。
6. 总结
<dlfcn.h> 提供了 运行时动态加载共享库 的能力,适用于:
- 插件化架构
- 延迟加载
- 跨平台模块管理

浙公网安备 33010602011771号