Rust 笔记
与 c++ 互操作
1. C++ 转 Rust (在 Rust 中调用 C++)
这是最常见的场景,通常用于复用现有的 C++ 库。
-
传统方式 (bindgen + build.rs):
bindgen会解析 C/C++ 头文件,自动生成 Rust 的 FFI 绑定代码。-
步骤:
- 编写 C++ 头文件 (
example.h) 和源文件。 - 在 Rust 项目的
build.rs中使用bindgen生成bindings.rs。 - 在
main.rs中引入生成的绑定。
- 编写 C++ 头文件 (
-
代码示例:
// build.rs fn main() { // 告诉 cargo 链接 C++ 库 println!("cargo:rustc-link-lib=static=my_cpp_lib"); // 生成绑定 let bindings = bindgen::Builder::default() .header("wrapper.h") .parse_callbacks(Box::new(bindgen::CargoCallbacks)) .generate() .expect("Unable to generate bindings"); bindings.write_to_file("src/bindings.rs").expect("Couldn't write bindings"); }
-
-
现代方式 (autocxx): 如果你觉得
bindgen生成的代码太底层且不安全(全是unsafe块),Google 开发的autocxx是一个更好的选择。它在bindgen之上提供了一层安全封装,能自动处理 C++ 的构造函数、析构函数和方法调用。
2. Rust 转 C++ (在 C++ 中调用 Rust)
这通常用于将 Rust 编写的高性能或安全模块集成到现有的 C++ 项目中。
-
基础方式 (C-ABI): 这是最稳健的方法。Rust 导出
extern "C"接口,C++ 直接调用。- Rust 端:使用
#[no_mangle]和extern "C"防止名称修饰,并使用#[repr(C)]确保结构体内存布局一致。 - C++ 端:声明对应的
extern "C"函数原型。
// Rust 代码 #[no_mangle] pub extern "C" fn add_numbers(a: i32, b: i32) -> i32 { a + b } #[repr(C)] pub struct Point { x: f64, y: f64, } - Rust 端:使用
-
现代方式 (cxx-rs):
// Rust 端 (src/lib.rs) // 需要添加依赖: cxx = "1.0" #[cxx::bridge] mod ffi { // 声明我们要调用的 C++ 函数 extern "C++" { // 包含 C++ 头文件 include!("example.h"); // 声明 C++ 函数原型 fn do_cpp_thing(x: i32) -> i32; } // 声明我们要暴露给 C++ 的 Rust 函数 extern "Rust" { fn do_rust_thing(input: &str) -> i32; } } // 实现 Rust 函数 fn do_rust_thing(input: &str) -> i32 { println!("Rust received: {}", input); 42 }