1.创建项目
cargo new --lib c-to-rust
生成lib.rs文件和Cargo.toml
2.编辑lib.rs的内容
#![crate_type = “staticlib”]
的作用就是指定rustc编译成什么库类型,这里指定为静态库类型。
rustc默认编译产生rust自用的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
}
3.编辑Cargo.toml的内容
[package]
name = "c-to-rust"
version = "0.1.0"
[lib]
name="2_3"
crate-type = ["staticlib"]
这里上面package没啥好说的,就是项目的相关信息。下面的lib和lib.rs同名,name为编译生成之后的lib库的名字,生成lib2_3.a静态库和其他一些编译之后东西。crate-type和上面的那个一样,可以只写在一个地方,一定要写在toml中。
4.rust编译
完成了lib.rs和Cargo.toml之后,就可以进行编译了。
很容易,直接用cargo,也可以写个makefile文件统一完成整个项目。
cargo build
会生成一个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\n", input, output);
printf("%d * 3 = %d\n", input, output2);
return 0;
}
这里就和写正常C语言代码差不多,有几个地方注意一下,声明一下要使用的rust函数。
6.使用gcc编译C语言代码
gcc -o test_c main.c lib2_3.a -lpthread -ldl
使用gcc编译,-o表示生成test_c可执行文件,需要main.c和lib2_3.a两个文件进行编译。后面的-lpthread和-ldl都是和库的参数。
7.大功告成,直接运行生成的test_c
./test_c
这里的命令还不是很多,如果多的话可以写个makefile文件来统一编译。
直接在文件夹里面make即可,make clean是清除make的结果,非常方便,这里附上代码,关于怎么写网上有很多教程。
ifeq ($(shell uname),Darwin)
LDFLAGS := -Wl,-dead_strip
else
LDFLAGS := -Wl,--gc-sections -lpthread -ldl
endif
all: target/c-to-rust
target/c-to-rust
target:
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 build
target/main.o: src/main.c | target
$(CC) -o $@ -c $<
clean:
rm -rf target