跳到主要内容

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 调用。

相关链接