与 C++ 的互操作性
Rust 社区提供了多种 C++/Rust 互操作选项,并且一直在不断开发新工具。目前,Chromium 使用一种名为 CXX 的工具。
您可以使用接口定义语言(与 Rust 极为相似)描述整个语言边界,然后 CXX 工具会据此生成 Rust 和 C++ 函数及类型的声明。
See the CXX tutorial for a full example of using this.
请仔细研究这个图表。解释背后的原理和您之前所做的完全相同。说明自动执行这一流程具有以下好处:
- 使用该工具可保证 C++ 端和 Rust 端相匹配(例如,如果
#[cxx::bridge]
与实际的 C++ 或 Rust 定义不匹配,则会出现编译错误。但使用不同步的手动绑定,可能会导致未定义行为) - 该工具还可自动生成 FFI thunk(即小型但可兼容 C-ABI 的自由函数),以便适应非 C 语言特性(例如,启用对 Rust 或 C++ 方法的 FFI 调用;而手动实现绑定一般需要自行编写这种顶级的自由函数)
- 该工具和库可以处理一系列核心类型,例如:
&[T]
可以跨 FFI 边界进行传递,即使它无法保证任何特定的 ABI 或内存布局一致无误。进行手动绑定时,必须手动解构std::span<T>
/&[T]
,并根据指针和长度进行重新构建,但这很容易出错,因为每种语言对于空 slice 的表示方式略有不同- 系统对
std::unique_ptr<T>
、std::shared_ptr<T>
和/或Box
等智能指针提供原生支持。如果使用手动绑定,则必须传递可兼容 C-ABI 的原始指针,这会增加生命周期和内存安全风险。 rust::String
和CxxString
类型能够识别并处理不同语言之间在字符串表示方面的差异(例如,rust::String::lossy
可以通过非 UTF8 输入构建 Rust 字符串;rust::String::c_str
可以为字符串加上 NUL 终止符)。