本页目录
裸指针与 FFI
*const T和*mut T不受借用检查器约束——可以随意别名、可以不指向合法内存。它们存在的唯一理由是 FFI:调用 C 库、接收 C 的回调、操作硬件寄存器。unsafe 块不是"禁用安全检查",而是把安全责任从编译器转移到程序员。
裸指针: 没有 borrow checker 的指针
let x = 42;
let ptr: *const i32 = &x; // 引用 → 裸指针 (安全)
unsafe
裸指针不需要遵守 borrow checker 规则——你可以有多个 *mut T 指向同一数据、可以是 null、可以不保证 alignment。所有 responsibility 转移到程序员。
与 C int * 的区别:Rust 区分 *const T 和 *mut T(类似 C 的 const int * vs int *)。但 C 可以隐式丢弃 const,Rust 不行。
extern "C": C 函数接口
extern "C"
// 禁止 Rust name mangling
pub extern "C"
extern "C" 使用 C calling convention:参数在寄存器/栈中按目标平台的 C ABI 排列。x86-64 上这是 System V AMD64 ABI(rdi, rsi, rdx, rcx, r8, r9 传参)。也可以使用 extern "system" (Windows API) 和 extern "Rust" (默认)。
#[repr(C)]: C 兼容的内存布局
// size: 16 bytes
没有 #[repr(C)] 时,Rust 编译器可以重排字段顺序以优化 struct 大小。加上 #[repr(C)] 后,字段按声明顺序,按 C ABI 要求 padding——保证与 C struct 二进制兼容。#[repr(C, packed)] 消除所有 padding(但可能产生未对齐引用——unsafe)。
bindgen: 自动生成 Rust FFI 绑定
从 C header 生成 Rust 的 extern 声明、struct 定义和常量:
// build.rs:
// src/lib.rs:
include!;
Callback: C 调 Rust 的陷阱
extern "C"
unsafe
Rust 函数作为 callback 传给 C 时,panic 不能跨越 FFI 边界——如果 callback 中 panic,且 unwind 穿过 C 栈帧,这是 UB(C 栈上没有 unwind tables)。解决方案:在 callback 中用 std::panic::catch_unwind 捕获 panic,或在 Cargo.toml 中设 panic = "abort"。
参考
- Rustonomicon: FFI, C ABI
- bindgen: rust-lang.github.io/rust-bindgen
- The Embedded Rust Book: FFI and C interaction
*Keywords: raw pointer, *const, mut, extern "C", #[no_mangle], repr(C), bindgen, FFI callback, C ABI