FFI 与 C 互操作
问题
Rust 如何与 C/C++ 代码互操作?
答案
Rust 调用 C
// 声明外部 C 函数
extern "C" {
fn abs(input: i32) -> i32;
fn strlen(s: *const std::ffi::c_char) -> usize;
}
fn main() {
unsafe {
println!("abs(-5) = {}", abs(-5));
}
}
C 调用 Rust
// 导出为 C 函数
#[no_mangle]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
a + b
}
Cargo.toml
[lib]
crate-type = ["cdylib"] # 动态库
安全封装
use std::ffi::{CStr, CString};
// 安全的字符串转换
fn safe_strlen(s: &str) -> usize {
let c_string = CString::new(s).expect("字符串包含 null 字节");
unsafe { strlen(c_string.as_ptr()) }
}
常用工具
| 工具 | 作用 |
|---|---|
bindgen | 从 C 头文件自动生成 Rust 绑定 |
cbindgen | 从 Rust 代码生成 C 头文件 |
cc crate | 在 build.rs 中编译 C 代码 |
cxx crate | 安全的 C++ 互操作 |
常见面试问题
Q1: FFI 调用为什么需要 unsafe?
答案:
Rust 编译器无法验证外部代码的安全性。C 函数可能:
- 接收空指针
- 缓冲区溢出
- 返回悬垂指针
- 不是线程安全的
这些都超出了 Rust 借用检查器的能力范围。最佳实践是用安全的 Rust 函数包装 unsafe FFI 调用。