I want extern "fil-c"
I want extern “fil-c”
Rust’s C FFI gives us access to decades of useful software, but the bargain is backwards. We use Rust to prove memory safety at compile time. Then we cross an unsafe boundary and trust the C library to respect a contract that neither language can enforce. The legacy code remains the cheap path, while rewriting it is the expensive one. Rust 的 C FFI(外部函数接口)让我们能够使用数十年来积累的实用软件,但这种交易方式是本末倒置的。我们使用 Rust 在编译时证明内存安全,然后跨越一个不安全的边界,寄希望于 C 库能遵守一种双方语言都无法强制执行的契约。遗留代码依然是低成本的选择,而重写它则代价高昂。
Fil-C offers a more interesting bargain. It recompiles C and C++ with capabilities, runtime checks, and a concurrent garbage collector. Memory-safety violations panic instead of becoming exploits. Existing software often needs few or no source changes, but it pays for safety at runtime. Fil-C 提供了一种更有趣的方案。它通过能力(capabilities)、运行时检查和并发垃圾回收机制来重新编译 C 和 C++ 代码。内存安全违规会触发 panic,而不是演变成漏洞利用。现有的软件通常只需极少甚至无需修改源码,但代价是运行时需要为安全性付出性能开销。
I want a Rust FFI that speaks the Fil-C ABI. The first version could be deliberately narrow: scalar values, copied strings and slices, and opaque handles. It would generate safe Rust wrappers, compile the complete C dependency graph with Fil-C, and provide no escape hatch back to ordinary unsafe C. Shared memory could come later, once the bridge can give Fil-C a capability that Rust can reliably revoke. 我想要一种支持 Fil-C ABI 的 Rust FFI。第一个版本可以刻意做得简单:仅支持标量值、拷贝字符串和切片,以及不透明句柄(opaque handles)。它将生成安全的 Rust 包装器,使用 Fil-C 编译完整的 C 依赖图,并且不提供回到普通不安全 C 代码的“后门”。共享内存可以在后续实现,前提是该桥接机制能赋予 Fil-C 一种 Rust 可以可靠撤销的能力。
This is not a new option for bindgen. Fil-C is source-compatible with C but intentionally not ABI-compatible, and ordinary Rust extern “C” speaks the ABI Fil-C calls Yolo-C. Building the bridge means teaching Rust, Fil-C, or a pair of generated stubs how to exchange values without losing Fil-C’s guarantees. If it were easy, it would already exist.
这并不是 bindgen 的一个新选项。Fil-C 虽然在源码层面兼容 C,但刻意在 ABI 层面不兼容,而普通的 Rust extern "C" 使用的是 Fil-C 所称的“Yolo-C” ABI。构建这座桥梁意味着要让 Rust、Fil-C 或一对生成的存根(stubs)学会如何在不丢失 Fil-C 安全保证的前提下交换数据。如果这很容易,它早就实现了。
One important part of this stack is already taking shape. filnix packages Fil-C as a Nix cross-compilation platform and has ports for more than 100 nixpkgs packages. Treating Fil-C as a platform means Nix rebuilds the transitive dependency closure for the Fil-C ABI instead of accidentally linking ordinary C into it. filnix is not the Rust bridge yet, but it provides the reproducible toolchain, package universe, and test bed where one could be built. 这个技术栈的一个重要部分已经初具雏形。filnix 将 Fil-C 打包为 Nix 交叉编译平台,并已移植了超过 100 个 nixpkgs 软件包。将 Fil-C 视为一个平台意味着 Nix 会为 Fil-C ABI 重建传递依赖闭包,而不是意外地链接入普通的 C 代码。filnix 虽然还不是 Rust 桥接器,但它提供了可复现的工具链、软件包生态和测试环境,可以在此基础上构建桥接器。
Zig is approaching the same problem from another direction. Andrew Kelley has proposed an optional fil ABI inspired by Fil-C. It would be an independent implementation in the Zig compiler and standard library, intended to compile a Zig program and its entire C and C++ dependency tree with runtime memory safety. That is remarkably close to the world a Rust bridge would need to enter.
Zig 正从另一个方向解决同样的问题。Andrew Kelley 提议了一种受 Fil-C 启发的可选 fil ABI。这将是 Zig 编译器和标准库中的独立实现,旨在编译 Zig 程序及其整个 C 和 C++ 依赖树,并实现运行时内存安全。这与 Rust 桥接器所追求的目标非常接近。
But the result would give us exactly the right incentives. We could use Rust for compile-time safety and then pay a performance penalty for using C. Keep the legacy library and it remains memory-safe, but every pointer operation is checked and its memory participates in garbage collection. Rewrite the hot path in Rust and those checks become static, so the tax disappears. C becomes the safe compatibility path rather than the permanent fast path. 但最终的结果将为我们提供正确的激励机制。我们可以利用 Rust 实现编译时安全,然后为使用 C 代码支付一定的性能代价。保留遗留库的同时确保其内存安全,每个指针操作都会被检查,其内存也会参与垃圾回收。当我们将热点路径用 Rust 重写后,这些检查就会变成静态的,性能损耗随之消失。C 将成为一种安全的兼容路径,而非永久的“快速通道”。
“100% safe” here means memory-safe across the whole supported boundary, not free of logic bugs, deadlocks, or bad APIs. That boundary is the hard part. Fil-C currently requires the whole program and its dependencies to use its ABI. The project also treats interoperability with ordinary C as a non-goal. A Rust bridge would have to preserve that whole-world guarantee rather than quietly punching a Yolo-shaped hole through it. 这里的“100% 安全”是指在整个支持的边界内实现内存安全,而不是指没有逻辑错误、死锁或糟糕的 API 设计。这个边界正是难点所在。Fil-C 目前要求整个程序及其依赖项都使用其 ABI。该项目也将与普通 C 代码的互操作性视为非目标。而 Rust 桥接器必须维护这种“全系统”的安全保证,而不是悄悄地在其中留下一个“Yolo 式”的漏洞。
I want extern “fil-c”: Rust on the fast path, old C on the safe path, and a performance reason to finish the migration. I would also like to see cross-ecosystem collaboration instead of several almost-compatible islands. Fil-C has the capability model and working runtime. Rust has compile-time safety. Zig is exploring a Fil-C-inspired ABI. Nix and filnix can rebuild and test complete dependency graphs. This problem deserves the best minds from all four communities in the same room.
我想要 extern "fil-c":让 Rust 走快速通道,让旧的 C 代码走安全通道,并提供一个基于性能的动力来完成迁移。我更希望看到跨生态系统的协作,而不是各自为政的孤岛。Fil-C 拥有能力模型和可用的运行时;Rust 拥有编译时安全;Zig 正在探索受 Fil-C 启发的 ABI;Nix 和 filnix 可以重建并测试完整的依赖图。这个问题值得这四个社区中最优秀的人才齐聚一堂共同探讨。
So here is the invitation: join us at OceanSprint next year in Lanzarote and build it together. Mikael Brockman, who is building filnix, has already accepted. Who else is joining us? 因此,这是一份邀请:明年在兰萨罗特岛(Lanzarote)举行的 OceanSprint 上加入我们,共同构建它。正在开发 filnix 的 Mikael Brockman 已经接受了邀请。还有谁愿意加入我们?