对于使用FFI包装C代码的代码(通常是crates), 如何保持Rust定义和C标头同步?或者确保它们与之匹配?
是否有工具来处理这个问题,或者每个开发人员都有责任手动检查这个?
更新:使这更具体。 有没有办法知道什么时候:
因此,任何与Rust代码不匹配都可以警告或无法完全编译?
我在箱子里遇到了崩溃,我怀疑它是由API不匹配导致的,但仍未报告但未固定。
答案 0 :(得分:2)
bindgen!
模块获取C头文件并在编译时生成Rust绑定。示例from the bindgen documentation:
#![feature(plugin)]
#![plugin(bindgen)]
mod lua_bindings {
bindgen!("/usr/include/lua.h", link="lua", builtins=true)
}
它将clang
添加为代码的复杂性,并依赖于每晚生锈。不幸的是,这会使你的项目繁重(依赖性)并且每晚都会生锈,但它有助于你的FFI绑定保持最新,加上交叉架构问题可以归结为知道每个架构的头文件的位置。
根据我的经验,bindgen工作得很好,它有一些限制因此它不适用于所有情况。
Libc采取了另一种方法。 Libc基本上由当前18种支持的体系结构的仅 FFI绑定组成,因此它对FFI绑定的正确性有着相当大的要求。
在Libc中,绑定是手工完成的(通常在running bindgen
in commandline的帮助下),然后使用https://github.com/alexcrichton/ctest
它是如何工作的,你指定要检查的所有C头,然后库将它与你在代码中指定的extern fn
定义进行比较,并确保..
所有函数签名,常量值,结构布局/对齐,类型大小/对齐等都与它们的C等价物相匹配(引自the docs)
将travis扔进混合中,你可以确保你的FFI绑定对于所有支持的体系结构中的每个代码更改都是正确的(看看libc's pull requests每次拉动都会自动通过travis运行并让作者纠正所有PR合并前的错误。)