You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dlopen/dlsym加载C++共享库时dlsym返回NULL的问题

问题根源:C++的名字修饰(Name Mangling)

你遇到的dlsym返回NULL的核心原因是C++编译器会对函数名进行名字修饰,而你在C代码里尝试查找的是未修饰的原始函数名"nothing",两者不匹配。

从你提供的nm -D sym.so输出可以看到,实际导出的符号是_Z7nothingv,这是GCC对C函数nothing()进行名字修饰后的结果。C通过这种方式支持函数重载等特性,但这就导致C代码(比如你的symtest.c)无法直接通过原始函数名找到C++编译的函数。

解决方案:用extern "C"禁用名字修饰

修改你的sym.cpp,用extern "C"包裹函数的声明和定义,强制编译器按照C语言的规则生成符号名,避免名字修饰:

extern "C" int nothing();
extern "C" int nothing() {
    return 0;
}

或者更简洁的写法:

extern "C" {
int nothing() {
    return 0;
}
}

验证修改效果

重新编译共享库和测试程序:

$ g++ -shared -fPIC -o sym.so sym.cpp
$ gcc symtest.c -ldl -o symtest
$ ./symtest

这次运行后不会输出NULL,因为dlsym现在能找到正确的符号nothing。你也可以用nm -D sym.so再次验证,会看到导出的符号变成了:

0000000000000670 T nothing

关联Redis模块场景的解释

回到你提到的Redis模块问题:Redis是用C语言编写的,它会在加载模块时查找RedisModule_OnLoad这个C风格的符号。如果你的模块用C编写但没有用extern "C"导出该函数,C编译器会对它进行名字修饰,导致Redis找不到对应的符号,从而报错"does not export RedisModule_OnLoad() symbol"。解决方法也是一样的——用extern "C"包裹RedisModule_OnLoad的定义。

内容的提问来源于stack exchange,提问作者Sidd Singal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:17:09