如何在Rust中使用C FFI的代码与标题保持同步?

时间:2017-01-14 15:34:50

标签: c rust ffi

对于使用FFI包装C代码的代码(通常是crates), 如何保持Rust定义和C标头同步?或者确保它们与之匹配?

是否有工具来处理这个问题,或者每个开发人员都有责任手动检查这个?

更新:使这更具体。 有没有办法知道什么时候:

  • 结构的成员更改其类型。
  • 函数参数更改其类型。

因此,任何与Rust代码不匹配都可以警告或无法完全编译?

我在箱子里遇到了崩溃,我怀疑它是由API不匹配导致的,但仍未报告但未固定。

1 个答案:

答案 0 :(得分:2)

解决方案1:bindgen

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工作得很好,它有一些限制因此它不适用于所有情况。

解决方案2:ctest

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合并前的错误。)