在 Rust 中调用 C 函数,需要对外部语言作出声明,往往使用 bindgen 等工具自动生成。Bindgen 在 build script 中运行,在编译 Rust 代码前先针对列出的头文件生成 C 函数的声明。

但是它不能对 inline 函数生成声明,而有些 C 库往往 inline 函数特别多。这时可以:

  1. 重新编译 C 库,阻止 inline。
  2. 用 Rust 重写一遍 inline 函数。(人类的本质是编译器)
  3. 在 inline 函数外面套一层不 inline 的 C 函数。

理想情况下采用 2,毕竟如果是常用的函数,inline 有它的道理。但是碰到了一个情况,某个 inline 函数访问了一个 thread_local 变量,而使用 Rust 重写时,访问这个变量需要先声明它。Rust 标准库不允许声明 thread_local,这就需要使用一个 unstable feature #[thread_local] (tracking issue)。

如果不想让工具链版本变成 nightly 的话,只能在外面套一层自己写的 C 函数、去调用 inline 函数。需要增加 stub.h、stub.c 等文件放置皮套函数。这样 build script 中所做的事就是:

  1. 编译 stub.c,可以使用 cc
  2. 通过 bindgen 生成声明,注意把 stub.h 也加进去。
  3. 通过 println!("cargo:rustc-xxx") (build script doc) 配置一些动态链接库等。