在 Rust 中调用 C 函数,需要对外部语言作出声明,往往使用 bindgen 等工具自动生成。Bindgen 在 build script 中运行,在编译 Rust 代码前先针对列出的头文件生成 C 函数的声明。
但是它不能对 inline 函数生成声明,而有些 C 库往往 inline 函数特别多。这时可以:
- 重新编译 C 库,阻止 inline。
- 用 Rust 重写一遍 inline 函数。
(人类的本质是编译器) - 在 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 中所做的事就是:
- 编译 stub.c,可以使用 cc 。
- 通过 bindgen 生成声明,注意把 stub.h 也加进去。
- 通过
println!("cargo:rustc-xxx")
(build script doc) 配置一些动态链接库等。