dlsym()
只能解析 C 符号,不能直接解析 C++ 符号。这是因为 C++ 支持 函数重载,编译器会对符号进行 名称修饰(Name Mangling),而 dlsym()
只能按字符串匹配符号名。
如何用 dlsym()
获取 C++ 符号?
方法 1:使用 extern "C"
如果你能修改库的源码,可以用 extern "C"
让 C++ 函数使用 C 语言的符号格式:
extern "C" void my_function() {
// 你的 C++ 代码
}
这样 dlsym()
就能直接找到 my_function
。
方法 2:手动查找修饰后的符号
如果库是别人提供的,无法修改源码,可以:
-
用
nm
命令查看符号:nm -D libyourlibrary.so | c++filt
这会显示 所有导出的符号,并解析 C++ 名称修饰。
-
在
dlsym()
里用修饰后的符号名: 例如nm
结果显示:0000000000001234 T _Z10my_functionv
你可以这样:
void* handle = dlopen("libyourlibrary.so", RTLD_LAZY); auto func = (void(*)())dlsym(handle, "_Z10my_functionv"); if (func) func();
方法 3:用 RTLD_GLOBAL
+ reinterpret_cast
有些库的 C++ 符号会间接暴露,你可以:
void* handle = dlopen("libyourlibrary.so", RTLD_LAZY | RTLD_GLOBAL);
typedef void (*MyFunctionType)();
MyFunctionType func = reinterpret_cast<MyFunctionType>(dlsym(handle, "_Z10my_functionv"));
if (func) func();
但这样要 确保符号匹配,否则可能崩溃。
方法 4:使用 c++filt
解码 C++ 符号
如果你只知道 C++ 函数原型:
void my_function(int);
你可以用 c++filt
反混淆:
echo '_Z11my_functioni' | c++filt
这能帮你找到正确的符号。
结论
dlsym()
只能解析 C 符号
解决方法:
-
extern "C"
(最简单) -
nm -D
+c++filt
查找修饰符号 -
RTLD_GLOBAL 方式
-
手动使用 C++ 编译器的符号修饰格式