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 的细节因平台/工具链而异;以实际工程配置为准。

结合场景再看三个关注点

  1. 跨边界无借用检查器
  2. 谁 free 内存必须写清
  3. 字符串用 CString/CStr

核心概念与准确模型

  • ABI:"C" 最常见
  • 表示:repr(C) 结构体布局
  • 工具:bindgencbindgen
  • 回调、线程、异常(C++)更复杂

设计动机

  • 复用生态
  • 渐进迁移
  • 性能关键路径

边界与误区

  • String 指针直接丢给 C
  • 忽略对齐/打包
  • 在 FFI 边界 panic 穿越

[!warning] 常见误区:大量 pub unsafe fn 直接暴露 对外给 safe 封装。

工程实践

  1. 自动生成绑定
  2. 所有权表:谁分配谁释放
  3. 测试 + sanitizer/Miri 有限适用
  4. 文档与示例强制

本节总结

  • FFI 是契约工程
  • unsafe 薄封装
  • 布局与字符串是高发坑

自测题

  1. 为什么需要 repr(C)
  2. 谁应该 free C 分配的内存?
参考答案
  1. 保证与 C 兼容的字段布局。
  2. 按 API 契约,通常分配方或文档指定方。

延伸阅读与资料来源

资料类型支撑内容
The Book — FFI官方书extern
Rustonomicon — FFI官方FFI 细节
bindgen工具生成绑定
创建于 2026/7/15 更新于 2026/7/15