惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News | PayPal Newsroom
C
CERT Recently Published Vulnerability Notes
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AWS News Blog
AWS News Blog
Hacker News: Ask HN
Hacker News: Ask HN
The Hacker News
The Hacker News
H
Hacker News: Front Page
T
The Exploit Database - CXSecurity.com
Google Online Security Blog
Google Online Security Blog
S
Security Affairs
T
Tor Project blog
T
Threat Research - Cisco Blogs
The Last Watchdog
The Last Watchdog
GbyAI
GbyAI
WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
罗磊的独立博客
TaoSecurity Blog
TaoSecurity Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
T
The Blog of Author Tim Ferriss
L
LINUX DO - 最新话题
Scott Helme
Scott Helme
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy International News Feed
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V
Visual Studio Blog
L
Lohrmann on Cybersecurity
C
Check Point Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Spread Privacy
Spread Privacy
博客园 - 聂微东
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
博客园 - 叶小钗
W
WeLiveSecurity
U
Unit 42
量子位
J
Java Code Geeks
AI
AI
L
LangChain Blog

博客园 - PKICA

编译配置解答 git实用命令 rust底层设计理念值得注意的几个地方总结 rust可变引用作为函数参数的机理详解 Rust内存重解释transmute C与Rust类型映射 rust延迟初始化原语 rust重借用机制与原理 rust参数传递模型 汇编语言语法详解 gdb汇编调试 gdb-pwndbg的安装与使用指南 gdb调试插件gef C语言thread_local linux系统readelf命令使用指南 gcore转储进程内存 gdb查看命令 RGB与YUV颜色编码的区别 Rust原子类型 C++ STL求两个集合交集差集 gdb调试集锦 ubuntu24.0.4使用root用户登录 ubuntu24.0.4输入密码后跳回登录界面 AI内存压缩技术TurboQuant及存疑 ubuntu切换到指定内核版本 在没有顶级科技大佬直接背书的情况下deepseek为啥能够异军突起? HuggingFace和deepseek的关系 当前主流AI大模型 Rust写时克隆Cow系列2
Rust FFI 安全抽象范式
PKICA · 2026-06-02 · via 博客园 - PKICA

在 C 与 Rust 的混合开发(FFI)中,FFI 黄金法则是确保跨语言调用时内存安全二进制对齐类型收敛以及

零运行时开销的核心准则。它是一套将 Rust 严格的编译期安全与 C 语言自由的底层指针进行完美接轨的工程

规范。

以下是针对开发及通用混合编程的 FFI 黄金法则 深度总结:

法则一:ABI 决定论(Application Binary Interface)

跨语言交互的本质不是代码转换,而是内存和寄存器级别的传参约定

  • 函数必须修饰:所有供 C 侧调用的 Rust 函数必须声明为 pub extern "C",以强迫 Rust 编译器采用标准的 C 语言调用约定(Calling Convention)。
  • 符号必须保活:必须附加 #[no_mangle] 属性,阻止 Rust 编译器混淆函数名,确保 cbindgen 能够识别并生成同名的 C 语言函数声明。
  • 布局必须强制:所有跨 FFI 传递的结构体,必须附加 #[repr(C)] 属性。这保证了 Rust 结构体中字段的内存顺序、对齐方式(Alignment)与 C 语言的 struct 严格保持 100% 一致。

法则二:所有权隔离法则(Ownership Quarantine)

内存泄漏与野指针(Use-After-Free)大多源于所有权边界的模糊。

  • 谁申请,谁释放:在 Rust 侧通过 Box::new() 申请的堆内存,如果转换成裸指针 *mut c_void 传给 C 侧,C 侧绝对不能调用 free() 去释放它。必须在生命周期结束时,将指针传回 Rust 侧,通过 Box::from_raw() 重新收回所有权并触发 Rust 的自动析构(Drop)。
  • 严禁跨边界解引用返回:在导出函数中,如果框架要求返回指针,严禁写成 return &mut *cntx必须通过指针级联强转(如 cntx as *mut _ as *mut c_void)或使用 Box::into_raw() 传递纯粹的内存地址

法则三:内聚不安全,外呈纯安全(Contain Unsafety)

unsafe 的污染范围控制在最小的单元内。

  • 签名保持 Safe:向 Rust 内部框架挂载的回调函数,定义上不要写 pub unsafe extern "C" fn。这会导致外部强类型检查失败。
  • 体内实施 Unsafe:正确的姿势是去掉签名的 unsafe,将其声明为普通的 pub extern "C" fn。仅在函数体内部需要处理 C 指针、执行 transmute 或解引用时,才开启 unsafe { ... } 代码块。
  • 入参非空引用:若 C 侧框架能确保传入的指针绝对不为 NULL,在 Rust 侧的回调定义中可以直接用 &mut SpaceShipState 代替 *mut _。Rust 框架会在入口处自动完成转换,使你在函数内部无需编写任何指针判空代码,直接享受 Safe Rust 的开发体验。

法则四:数据切片的“零拷贝”边界(Zero-Copy Slicing)

数据处理性能的生死线在于避免内存拷贝。

  • 指针 + 长度 $\rightarrow$ 视图:当 C 侧将数据流通过 const uint8_t *inputuint32_t input_len 传给 Rust 时,Rust 侧严禁将其分配(Allocate)到新的 Vec<u8> 中。
  • 利用 Slice 宏:必须立即使用类似 slice::from_raw_parts将其打包为 Rust 的切片 &[u8]。这只是创建了一个内存视窗(Window),开销为零,却能直接调用 Rust 强大的模式匹配和解析工具(如 nom 框架)。

参考实现:

#[macro_export]
macro_rules! build_slice {
    ($buf:ident, $len:expr) => {
        if $buf.is_null() && $len == 0 {
            &[]
        } else {
            unsafe { std::slice::from_raw_parts($buf, $len) }
        }
    };
}

法则五:工具链逆向解耦(Toolchain Isolation)

利用自动化工具(cbindgen)时,要学会“防御性编程”,防止类型污染。

  • 别名抹平冲突:当 Rust 侧要求 *const QuantumContext 而 C 侧老代码写死要求 QuantumContext * 时,不要强行修改任何一侧。在 Rust 侧声明一个别名 type QuantumContextPtr = *const core::QuantumContext;
  • 配置文件欺骗:在 cbindgen.toml 中配置 [export.rename] "QuantumContextPtr" = "QuantumContext *"。这样既满足了 Rust 侧的强类型回调注册,又强行让 cbindgen 在 C 头文件中吐出不带 const 的干净指针,实现了对既有老 C 代码的零侵入、零破坏。

注意:

如果 C 侧调用该函数时传入的是普通指针(*),而导出的头文件里声明的是常量指针(*const),这种情况下确实完全不需要使用类型别名去抹平冲突。

总结

FFI 黄金法则的核心思想可以浓缩为一句话:“在 C 的世界里展现 C 的规矩(提供统一的 void* 和 int 返回码),在 Rust 的世界里恪守 Rust 的方圆(内部强转为安全引用与 Safe 闭包)”。

参考资料:

rust工程化实践卷III juler