unsafe关键字
0. 新建一个InvokeC的工程
cargo new InvokeC
1.编辑 src/main.c
extern "C" {
fn doubler(x: i32) -> i32;
}
fn main() {
println!("[rust] start");
unsafe {
println!("{}", doubler(6));
}
}
2. 编辑 src/hello.c
#include stdio.h
int doubler(int x) {
return x * 2;
}
3.编译C代码
$ cc -c src/hello.c $ cc -shared hello.o -o libnum.so
4.用rustc 编译代码,并动态链接到 libnum
rustc -l num -L . src/main.rs
5. 运行
LD_LIBRARY_PATH=. ./main
如果不设置 LD_LIBRARY_PATH 变量, 将会找不到 libnu.so 动态库
6. 也考虑生成静态库
$ ar rcs libnum.a hello.o
7.链接到静态库
rustc -l static=num -L. src/main.rs
8.直接运行
./main
9. 如何不用rustc编译, 而是用cargo build或者cargo run
在项目的根目录下,建立一个 build.rs 文件
fn main() {
println!("cargo:rustc-link-search=.");
println!("cargo:rustc-link-lib=static=num");
}
就可以了
如果是动态库
println!("cargo:rustc-link-search=all=src"); // 类似"rustc -L src ..."
println!("cargo:rustc-link-lib=dylib=num"); // 类似"rustc -l num"
或者在源代码中 指定链接选项
main.c中
#[link(name = "num", kind = "static")]
extern "C" {
fn doubler(x: i32) -> i32;
}
...
就可以把 build.rs中
println!("cargo:rustc-link-lib=static=num");
这一行去掉
最后,如果连编译C代码都不想手动去做,可以用一个 cc的库, 在Cargo.toml中添加
[build-dependencies] cc = "1.0"
注意:是 build-dependencies 而不是 dependencies
然后,将 build.rs改为
fn main() {
cc::Build::new()
.file("src/hello.c")
.compile("libnum.a");
}
或者
fn main() {
cc::Build::new()
.file("src/hello.c")
.compile("anything");
}