• C语言和Rust语言的互相调用(1)(C调用Rust)


    1.创建项目

    cargo new --lib c-to-rust
    
    • 1

    生成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
    }
    
    • 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 
    #include 
    
    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;
    }
    
    • 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_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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    设计模式(二)-创建者模式(3)-抽象工厂模式
    亚马逊、OZON、速卖通等跨境电商平台卖家怎样快速提高产品权重?
    认识doubbo和rpc
    北大青鸟昌平校区:学软件测试有年龄限制吗?
    专业四第二周自测
    【C++笔试强训】第十七天
    JVM的内存结构
    sql语句 如果为空值显示为0
    配置pytorchGPU虚拟环境-python3.7
    RabbitMQ深入 —— 持久化和发布确认
  • 原文地址:https://blog.csdn.net/phthon1997/article/details/126467657