C++调用Rust后回调C++的链接报错问题(游戏模组场景)
问题根源
报错undefined reference to 'cpp'是因为Rust生成的动态库libexternal.so需要调用的C函数cpp(),在最终编译的C可执行文件中没有被导出,或者链接器无法在符号表中找到它。单独C调用Rust正常,说明单向调用的符号导出没问题,但双向调用时,C的函数符号没有对动态库开放。
解决步骤
1. 统一C++与Rust的函数符号规则
C默认会对函数名做名字修饰,导致Rust无法匹配到正确的符号。必须用extern "C"强制C生成无修饰的C风格符号:
- 在
main.h中声明:#ifndef MAIN_H #define MAIN_H extern "C" void cpp(); #endif - 在
main.cpp中实现:#include "main.h" #include "rust.h" #include <iostream> void cpp() { std::cout << "C++ function called from Rust" << std::endl; } int main() { rust(); return 0; }
2. 修正Rust中的函数声明
在Rust代码中,必须用extern "C"块声明要调用的C++函数,保证符号匹配:
比如cpp.rs中:
extern "C" { pub fn cpp(); } pub fn call_cpp() { unsafe { cpp(); } }
lib.rs中导出供C++调用的函数:
mod cpp; #[no_mangle] pub extern "C" fn rust() { cpp::call_cpp(); }
3. 调整C++编译命令,导出可执行文件符号
Linux下默认可执行文件不会导出全局符号,动态库无法引用其中的函数。必须添加-rdynamic参数让可执行文件导出符号:
g++ -L ./external/target/debug/ -Wall main.cpp -l external -rdynamic
-rdynamic会强制将可执行文件的全局符号加入动态符号表,让Rust的动态库能找到cpp()的实现。
4. 重新编译验证
- 先重新编译Rust动态库:
cd external && cargo build - 用上述命令编译C++程序
- 运行生成的可执行文件,即可看到Rust成功回调C++的
cpp()函数。
避坑提示
- 不要省略
extern "C":C++的名字修饰会让符号名变成类似_Z3cppv的形式,Rust根本找不到这个符号。 - 必须加
-rdynamic:没有这个参数,可执行文件的符号不会对外暴露,动态库永远找不到依赖的函数。 - 检查链接顺序:确保
-l external在源文件之后,链接器会按顺序解析符号,避免符号未定义的问题。
内容的提问来源于stack exchange,提问作者Rushmore75
相关产品推荐
相关产品推荐

