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"); }