Rust FFI
通过 C ABI 与外部语言互操作;安全封装、所有权跨边界与工具链要点。
#type / concept
#status / growing
#tech / dev
#resource / rust
[!info] 关联笔记
Rust FFI
这个概念为什么出现
现实系统有 C 库、OS API、其他语言运行时。
FFI(Foreign Function Interface)让 Rust 调用/被调用,但类型与所有权契约需人工保证。
[!abstract] 一句话理解
extern "C"声明 C ABI 函数;跨边界指针与生命周期必须在安全包装层校验;优先 bindgen 生成绑定,unsafe 留在薄封装内。
最小可运行示例
场景:调用 C 标准库 abs(示意)
// 业务意图:演示 extern 声明形状。
// 教学点:ABI;unsafe 调用;安全包装。
use std::os::raw::c_int;
extern "C" {
fn abs(input: c_int) -> c_int;
}
fn checked_abs(v: i32) -> i32 {
// SAFETY: libc abs 对 c_int 有定义;i32 与 c_int 在此平台假设兼容(教学简化)。
unsafe { abs(v) }
}
fn main() {
println!("abs={}", checked_abs(-12));
}
链接 libc 的细节因平台/工具链而异;以实际工程配置为准。
结合场景再看三个关注点
- 跨边界无借用检查器
- 谁 free 内存必须写清
- 字符串用
CString/CStr
核心概念与准确模型
- ABI:
"C"最常见 - 表示:
repr(C)结构体布局 - 工具:
bindgen、cbindgen - 回调、线程、异常(C++)更复杂
设计动机
- 复用生态
- 渐进迁移
- 性能关键路径
边界与误区
- 把
String指针直接丢给 C - 忽略对齐/打包
- 在 FFI 边界 panic 穿越
[!warning] 常见误区:大量 pub unsafe fn 直接暴露 对外给 safe 封装。
工程实践
- 自动生成绑定
- 所有权表:谁分配谁释放
- 测试 + sanitizer/Miri 有限适用
- 文档与示例强制
本节总结
- FFI 是契约工程
- unsafe 薄封装
- 布局与字符串是高发坑
自测题
- 为什么需要
repr(C)? - 谁应该 free C 分配的内存?
参考答案
- 保证与 C 兼容的字段布局。
- 按 API 契约,通常分配方或文档指定方。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — FFI | 官方书 | extern |
| Rustonomicon — FFI | 官方 | FFI 细节 |
| bindgen | 工具 | 生成绑定 |