在上一篇中,我们整体介绍了 cbindgen 工具。本文将会示例如何使用 cbindgen 为我们之前写的 Rust 示例库 生成头文件。主要内容包括:
- 生成的头文件和之前的对比
- 为 C API 增加枚举类型,并生成头文件
使用 cbindgen.toml
我们知道可以通过 cbindgen.toml 这个配置文件,给 cbindgen 工具配置各种行为参数来生成头文件。示例库提供了 C API,那我们首先在示例库的根目录下创建一个 cbindgen.toml ,并且试试只配置以下一行内容:
language = "C"
然后执行以下命令:
cbindgen --config cbindgen.toml --crate example_03 --output example_03_header.h
我们可以看到,在根目录下生成了一个 example_03_header.h 的头文件。跟我们之前手动编写的头文件进行对比:
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
多了以上这几行 #include
文件,这是 cbindgen 工具的默认行为,它会默认导入这些 C/C++ 标准库。 我们如果不需要导入这些库时,可以通过增加以下配置内容:
no_includes = true
再执行生成命令后,这时我们可以看到这个头文件和我们之前手动编写的基本一样。
这时,如果我们想要在导出的头文件中类型统一加个前缀,比如:capi_
,可以在 cbindgen.toml 增加以下配置:
[export]
prefix = "capi_"
增加枚举类型
为了演示 cbindgen 工具对 enum 枚举类型的支持,我们为示例增加个枚举类型,代码如下:
#[repr(C)]
#[derive(Debug)]
pub enum gender {
BOY,
GIRL,
}
同时,相应地修改函数中的一些代码:
#[no_mangle]
pub extern "C" fn student_alice() -> *mut student {
let mut init_char_array: [c_char; 20] = [0; 20];
for (dest, src) in init_char_array.iter_mut().zip(b"Alice\0".iter()) {
*dest = *src as _;
}
let scores = [92.5, 87.5, 90.0];
let alice = student {
num: 1 as c_int,
total: 280,
name: init_char_array,
scores,
gender: gender::GIRL,
};
Box::into_raw(Box::new(alice))
}
这时,通过 cbindgen 工具生成头文件,我们可以看出新的头文件能正确地包含我们新增的枚举类型:
typedef enum {
BOY,
GIRL,
} capi_gender;
对于枚举类型中的变体,如果我们希望更符合 C 的风格,可以在 cbindgen.toml 中配置以下内容:
[enum]
rename_variants = "SnakeCase"
这个规则是针对枚举类型的变体进行重命名,主要的值包括(引用自 cbindgen 的文档):
# possible values (that actually do something):
# * "CamelCase": MyVariant => myVariant
# * "SnakeCase": MyVariant => my_variant
# * "ScreamingSnakeCase": MyVariant => MY_VARIANT
# * "QualifiedScreamingSnakeCase": MyVariant => ENUM_NAME_MY_VARIANT
# * "LowerCase": MyVariant => myvariant
# * "UpperCase": MyVariant => MYVARIANT
# * "None": apply no renaming
执行 cbindgen 后,可以看到头文件枚举部分的定义变为:
typedef enum {
boy,
girl,
} capi_gender;
小结
综上所述,我们演示了对于之前的 Rust 示例库,如何通过配置 cbindgen.toml 使用 cbindgen 生成头文件。
完整示例代码在 Github:https://github.com/lesterli/rust-practice/tree/master/ffi/example_03
hyper 的C API 也是通过 cbinggen 来生成头文件的,有兴趣的可以通过此链接围观。
评论区
写评论还没有评论