fn main() {
// 制定搜索路径
println!(r"cargo:rustc-link-search=./c-lib");
// 如果是动态链接库,在 macOS 上,编译成功之后,需要配置 DYLD_LIBRARY_PATH
// export DYLD_LIBRARY_PATH=.:$DYLD_LIBRARY_PATH
// 此时执行可执行文件才能成功。否则会提示 dyld: Library not loaded
// 待确定:如果是静态链接库,可以配置如下参数。编译成功之后,可以直接执行
// println!(r"cargo:rustc-link-lib=static=ext");
// 有兴趣可以试试 crate cc https://crates.io/crates/cc
// --crate-type=cdylib --crate-name=ext ext.c
// Tell Cargo that if the given file changes, to rerun this build script.
// println!("cargo:rerun-if-changed=c-lib/ext.c");
// Use the `cc` crate to build a C file and statically link it.
// cc::Build::new()
// .file("src/hello.c")
// .compile("hello");
}
Rust 有极强的跨平台性,对比 c/c++,又能解决野指针的问题,还能解决类型安全的问题。 所以,使用 Rust 编译出来的程序,可以以库的形式和其它程序进行连接,是不错的未来。
如果是编写 Nodejs 扩展,https://github.com/napi-rs/node-rs 是一个不错的开始。 如果是编写 wasm 项目,https://github.com/rustwasm/wasm-pack 是一个不错的开始。
本文仅仅从较低层面,讲解如何编译动态库,并在 c 和 rust 之间调用。
C 语言使用 Rust 函数
示例 c-app
第一步,配置 rust Cargo.tomal,使其输出 cdylib
第二步,编写 rust 代码,使用 extern 声明导出的函数。使用 cargo build 编译产出库文件 libhello.so,位置在 target/debug 文件夹下。(仅用于测试,如果是用于生产,请带上 --release)
第三步,编写 c 代码,引用 rust 写的功能函数
第四步,编译 c 代码,链接 Rust 动态链接库
-l
指定链接时需要的动态库,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a或.so来确定库-L
依赖库搜索路径Rust 使用 C 函数
示例 c-lib
第一步,编写 C 代码
第二步,编译
第三步,编写 Rust 代码,引用 C 函数
第四步,编写 build.rs。需要注意的是: 对于链接动态链接库,只需要配置
println!(r"cargo:rustc-link-search=./c-lib");
对于静态链接库,需要再增加配置(或者在 rust 代码里面 link 指定 kind 为 static 即可) https://doc.rust-lang.org/rustc/command-line-arguments.html#-l-link-the-generated-crate-to-a-native-library
println!(r"cargo:rustc-link-lib=static=ext");
其它文章参考
第五步,执行。对于动态链接库,需要配置
DYLD_LIBRARY_PATH
(macOs) /LD_LIBRARY_PATH
(Linux) 才能正常执行。否则提示dyld: Library not loaded
。另外,如果是静态编译,那么需要确保库所在位置只有静态库,不能有同名的动态库
rlib
如果是 rust 编译出来的库,则可以参考下面的例子。 使用 extern crate 导入。并在编译的时候,通过
--extern
参数指定依赖库的名称和地址