1.创建项目
cargo new --lib c-to-rust
- 1
生成lib.rs文件和Cargo.toml
2.编辑lib.rs的内容
#![crate_type = “staticlib”]
crm开发定制的作用就是指定rustccrm开发定制编译成什么库类型,crm开发定制这里指定为静态库类型。
rustccrm开发定制默认编译产生自用的rlib格式库,要让rustc产生动态链接库或者静态链接库,需要显式指定。
方法1: 在文件中指定。
在文件头加上#![crate_type = “foo”], 其中foo的可选类型有bin, lib, rlib, dylib, staticlib.分别对应可执行文件,
默认(将由rustc自己决定), rlib格式,动态链接库,静态链接库。
方法2: 编译时给rustc 传–crate-type参数。参数内容同上。
方法3: 使用cargo,指定crate-type = [“foo”], foo可选类型同1。
#[no_mangle]
的作用是由于rust支持重载,所以函数名会被编译器进行混淆,就像c++一样,加上这个就可以防止重名的错误,不修改函数名。
为了能让rust的函数通过FFI(Foreign Function Interface语言交互接口)被调用,需要加上extern "C"对函数进行修饰。
#![crate_type = "staticlib"]#[no_mangle]pub extern "C" fn double_input(input: i32) -> i32 { input * 2}#[no_mangle]pub extern "C" fn third_input(input: i32) -> i32 { input * 3}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
3.编辑Cargo.toml的内容
[package]name = "c-to-rust"version = "0.1.0"[lib]name="2_3"crate-type = ["staticlib"]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这里上面package没啥好说的,就是项目的相关信息。下面的lib和lib.rs同名,name为编译生成之后的lib库的名字,生成lib2_3.a静态库和其他一些编译之后东西。crate-type和上面的那个一样,可以只写在一个地方,一定要写在toml中。
4.rust编译
完成了lib.rs和Cargo.toml之后,就可以进行编译了。
很容易,直接用cargo,也可以写个makefile文件统一完成整个项目。
cargo build
- 1
会生成一个target文件,里面有我们需要的东西。
5.C语言主函数的编写
既然是c语言调用rust,那就应该是c语言里写主函数,rust里面的是函数。
#include <stdint.h>#include <stdio.h>extern int32_t double_input(int32_t input);extern int32_t third_input(int32_t input);int main(){ int input = 4; int output = double_input(input); int output2 = third_input(input); printf("%d * 2 = %d\", input, output); printf("%d * 3 = %d\", input, output2); return 0;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
这里就和写正常C语言代码差不多,有几个地方注意一下,声明一下要使用的rust函数。
6.使用gcc编译C语言代码
gcc -o test_c main.c lib2_3.a -lpthread -ldl
- 1
使用gcc编译,-o表示生成test_c可执行文件,需要main.c和lib2_3.a两个文件进行编译。后面的-lpthread和-ldl都是和库的参数。
7.大功告成,直接运行生成的test_c
./test_c
- 1
这里的命令还不是很多,如果多的话可以写个makefile文件来统一编译。
直接在文件夹里面make即可,make clean是清除make的结果,非常方便,这里附上代码,关于怎么写网上有很多教程。
ifeq ($(shell uname),Darwin) LDFLAGS := -Wl,-dead_stripelse LDFLAGS := -Wl,--gc-sections -lpthread -ldlendifall: target/c-to-rust target/c-to-rusttarget: mkdir -p $@target/c-to-rust: target/main.o target/debug/lib2_3.a $(CC) -o $@ $^ $(LDFLAGS)target/debug/lib2_3.a: src/lib.rs Cargo.toml cargo buildtarget/main.o: src/main.c | target $(CC) -o $@ -c $<clean: rm -rf target
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24