在Ubuntu系统上实现Rust与C/C++的互操作(FFI),实际上就是让不同语言编写的代码能够共享函数并相互调用。本文将从零开始,手把手带您搭建完整的Rust与C/C++交互流程,确保每一步都能顺利执行。

1. 安装Rust环境
首先需要确保系统中已正确安装Rust。如果尚未安装,只需执行以下命令即可完成:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
完成后建议通过 rustc --version 验证版本信息,确认安装无误。
2. 创建Rust库项目
本次将创建库项目而非可执行程序,因此使用 cargo new --lib 来初始化:
cargo new --lib my_rust_lib
cd my_rust_lib
3. 配置Cargo.toml
关键步骤:告知Cargo需要生成动态链接库(Linux环境下为 .so 文件)。编辑 Cargo.toml,在文件末尾添加以下配置:
[lib]
name = "my_rust_lib"
crate-type = ["cdylib"]
其中 cdylib 表示“C动态库”,编译后将生成 libmy_rust_lib.so。
4. 编写Rust函数
打开 src/lib.rs,编写一个可被C调用的函数。核心是使用 #[no_mangle] 和 extern "C" 属性,确保函数名不被混淆并遵循C的ABI:
#[no_mangle]
pub extern "C" fn rust_function() {
println!("Hello from Rust!");
}
实际项目中,此函数可承载任意复杂逻辑。
5. 编译Rust代码
执行编译命令:
cargo build --release
编译完成后,在 target/release 目录下即可找到 libmy_rust_lib.so 动态库文件。
6. 创建C/C++调用项目
接下来需要编写C或C++程序来调用上述Rust函数。两种语言的处理方式有所不同,分别说明。
C语言示例
创建 main.c 文件:
#include
// 声明Rust函数
void rust_function();
int main() {
printf("Calling Rust function...\n");
rust_function();
return 0;
}
编译时需指定链接路径和库名:
gcc -o my_c_program main.c -L/path/to/rust/library -lmy_rust_lib -lpthread -ldl
请将 /path/to/rust/library 替换为实际的 target/release 目录路径,例如 ./target/release。
C++语言示例
创建 main.cpp 文件:
#include
// 声明Rust函数
extern "C" void rust_function();
int main() {
std::cout << "Calling Rust function..." << std::endl;
rust_function();
return 0;
}
编译命令:
g++ -o my_cpp_program main.cpp -L/path/to/rust/library -lmy_rust_lib -lpthread -ldl
7. 运行程序验证
执行编译后的可执行文件:
./my_c_program
# 或
./my_cpp_program
若一切正常,输出结果应包含以下两行:
Calling Rust function...
Hello from Rust!
注意事项与最佳实践
- Rust与C/C++的编译器必须采用一致的ABI(应用程序二进制接口)。在Linux x86_64平台上,默认均使用System V ABI,通常不会出现冲突。
extern "C"是双方通信的桥梁,它指示Rust编译器按照C语言的约定暴露函数,使得C/C++能够正确识别并调用。- 内存管理与所有权需格外谨慎。Rust的所有权模型与C的malloc/free机制不能混用。传递复杂数据结构时,建议仅传递指针,或使用
CString、Box等安全封装进行交互。
通过以上七个步骤,您可以在Ubuntu上轻松实现Rust与C/C++的跨语言调用。实际生产环境可能涉及回调函数、结构体传递、错误处理等进阶场景,但底层框架与此一致。
