本页目录
C ABI 与 bindgen
Rust 调用 C 的第一步是让类型布局一致——
repr(C)强制 Rust struct 按 C ABI 排列字段,和 C header 里的结构体逐字节对齐。bindgen 从 C header 自动生成对应的 Rust 类型和函数签名,把手工维护 Rust/C 类型映射的枯燥和出错变成自动化。callback 安全的核心是:从 C 回调 Rust 时,panic 不能跨 FFI 边界 unwind。
C ↔ Rust 类型映射
FFI 的类型对应不是自动的——必须显式使用 std::os::raw 或 libc crate 中的 C 兼容类型:
| C type | Rust type (libc) | 注意 |
|---|---|---|
int | c_int (i32) | |
long | c_long | 32-bit on Windows, 64-bit on Linux! |
size_t | usize | |
char * (string) | *const c_char → CStr::from_ptr() | |
void * | *mut c_void | |
| struct pointer (opaque) | *mut MyStruct | 不解引用, 只传递 |
| enum | #[repr(C)] enum | C enum 是 c_int 大小 |
关键陷阱:long 的大小在 LLP64 (Windows) 上是 4 bytes,在 LP64 (Linux) 上是 8 bytes。如果你的 C 代码依赖 long 为 8 bytes,在 Windows 上用 i64 代替。
bindgen 自动化
bindgen 从 C header 自动生成 Rust 的外部函数声明、结构体和常量:
// build.rs
// src/lib.rs
include!;
bindgen 处理:基础类型映射、struct alignment、nested structs、function pointers、conditional defines。不能处理:inline functions (需手动 port 为 Rust)、C++ templates。
Callback: C 调 Rust 的安全边界
extern "C"
unsafe
callback 中 panic 不能跨越 FFI 边界——这会产生 UB。在 Cargo.toml 中设 panic = "abort" 是免除这种风险的最直白方式。如果必须保留 unwinding,在 callback 中用 catch_unwind 包裹所有逻辑。
参考
- bindgen: rust-lang.github.io/rust-bindgen
- Rustonomicon: FFI
- libc crate: docs.rs/libc
Keywords: C ABI, bindgen, c_int, c_long, c_void, callback, panic across FFI, #[repr(C)]