crate-type = ["staticlib"],将新库配置为编译为静态库。
接下来,你需要使用 Corrosion 库将该库链接到 CMake。第一步是在 /rust 文件夹内的 CMakeLists.txt 中添加该库所在的文件夹。之后,你应在该库目录中添加 CMakeLists.txt 文件。在该文件中,需要调用 Corrosion 的导入函数。导入 BLAKE3 时使用了以下几行代码:
_ch_rust_blake3 这个名称来自 Cargo.toml,其中它被用作项目名称 (name = "_ch_rust_blake3") 。
由于 Rust 数据类型与 C/C++ 数据类型不兼容,我们将利用这个空库项目创建 shim 方法,用于转换从 C/C++ 接收的数据、调用库方法,以及将输出数据反向转换回来。例如,下面这个方法就是为 BLAKE3 编写的:
fill() 方法直接写入指针,因此不需要进行这种转换。这里的主要建议是尽量少创建方法,这样一来,每次调用方法时需要做的类型转换就更少,也不会带来太多额外开销。
值得注意的是,#[no_mangle] 属性和 extern "C" 对所有这类方法都是必需的。没有它们,就无法进行正确的 C/C++ 兼容编译。此外,它们对于集成的下一步也是必不可少的。
编写完 shim 方法的代码后,我们需要为该库准备请求头。这可以手动完成,也可以使用 cbindgen 库自动生成。如果使用 cbindgen,你需要编写一个 build.rs 构建脚本,并将 cbindgen 作为构建依赖引入。
可自动生成请求头的构建脚本示例:
#[no_mangle] 属性和 extern "C"。否则,库可能会被错误编译,且 cbindgen 无法自动生成请求头。
完成上述所有步骤后,你可以在一个小型项目中测试你的库,以找出兼容性或请求头生成方面的各种问题。如果在生成请求头时出现任何问题,可以尝试通过 cbindgen.toml 文件进行配置 (你可以在这里找到一个模板:https://github.com/eqrion/cbindgen/blob/master/template.toml) 。
还需要指出的是,在集成 BLAKE3 时曾遇到一个问题:
MemorySanitizer 可能会导致误报,因为它无法判断 Rust 中某些变量是否已经初始化。这个问题最终通过编写一个对部分变量作出更明确声明的方法得到解决,不过这种方法的实现速度较慢,仅用于修复 MemorySanitizer 构建。