• C中分配堆栈,Rust中填充使用


    预先知识点:

    结构体

    实践1

    实践的步骤分为以下几步:
    1.Rust 导出一个 so 库
    2.main 函数在 C 这边,链接 Rust 的 so 库
    3.C 中分配栈内存,交由 Rust 端填充
    4.Rust 端打印
    5.C 端打印

    Rust端的代码:

    // src/lib.rs
    use std::os::raw::c_int;
    use std::slice;
     
    #[repr(C)]
    #[derive(Debug)]
    pub struct Student {
        pub num: c_int,
        pub total: c_int,
    }
     
    #[no_mangle]
    pub extern "C" fn fill_students(p_stu: *mut Student, n: c_int) {
        assert!(!p_stu.is_null());
        let s: &mut [Student] = unsafe { slice::from_raw_parts_mut(p_stu, n as usize) };
        for elem in s.iter_mut() {
            // fill any valid values
            elem.num = 1 as c_int;
            elem.total = 100 as c_int;
        }
    }
     
    #[no_mangle]
    pub extern "C" fn print_students(p_stu: *mut Student, n: c_int) {
        assert!(!p_stu.is_null());
        let s: &[Student] = unsafe { slice::from_raw_parts(p_stu, n as usize) };
        for elem in s.iter() {
            println!("print in rust side: {:?}", elem);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    代码解释:
    1.Rust代码中定义了一个结构体,有两个函数,一个是对C端传来的结构体进行填充,另一个是打印C端传来的结构体。
    2.C代码中是一个生成一个结构体数组,传入数组名,这边用结构体指针进行接收,传数组之前说过需要告知长度,s就是可变切片类型,另一个打印不需要可变类型,这里注意Rust对于可变不可变做了很不同的使用方式。
    3.isize 和 usize 两种整数类型是用来衡量数据大小的,它们的位长度取决于所运行的目标平台,如果是 32 位架构的处理器将使用 32 位位长度整型。

    C语言代码:

    // csrc/cfoo1.c
    #include
    #include
    #include
    typedef struct Students {
            int num;                // serial number
            int total;              // total score
    } Student;
     
    extern void fill_students(Student *stu, int);
    extern void print_students(Student *stu, int);
     
    void print_students_c(Student *stu, int n) {
            int i;
            for (i=0; i<n; i++) {
                    printf("C side print: %d %d\n", stu[i].num, stu[i].total);
            }
    }
     
    void main() {
            int len = 10;
            Student students[len];
     
            // call rust fill and print functions
            fill_students(students, len);
            print_students(students, len);
     
            // call c print function
            print_students_c(students, len);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    makefile代码:

    GCC_BIN ?= $(shell which gcc)
    CARGO_BIN ?= $(shell which cargo)
    
    run: clean build
    	./main
    
    clean:
    	$(CARGO_BIN) clean
    	rm -f ./main
    build:
    	$(CARGO_BIN) build
    	$(GCC_BIN) -o ./main ./src/main.c -Isrc -L. -l:./target/debug/libnew_test.so
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    实践2

    C 中分配堆内存,交由 Rust 端填充,并且两边分别打印。
    这里的Rust代码和上面的一样,主要是C语言代码如下:

    // csrc/cfoo2.c
    #include
    #include
    #include
     
    typedef struct Students {
            int num;                // serial number
            int total;              // total score
    } Student;
     
    extern void fill_students(Student *stu, int);
    extern void print_students(Student *stu, int);
     
    Student* create_students(int n) {
            if (n <= 0) return NULL;
            Student *stu = NULL;
            stu = (Student*) malloc(sizeof(Student)*n);
            return stu;
    }
     
    void release_students(Student *stu) {
            if (stu != NULL)
                    free(stu);
    }
    void print_students_c(Student *stu, int n) {
            int i;
            for (i=0; i<n; i++) {
                    printf("C side print: %d %d\n", stu[i].num, stu[i].total);
            }
    }
     
    void main() {
            int len = 10;
            Student* students = create_students(len);
     
            // call rust fill and print functions
            fill_students(students, len);
            print_students(students, len);
     
            // call c print function
            print_students_c(students, len);
            release_students(students);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    代码解释:
    1.这里的传递方式和上面还是一样的,只是这里的C语言部分,自己做了个申请,,定义了一个返回结构体指针的函数,这边的堆释放需要手动完成。

    我们从两个示例的对比可以看到,C 这边栈和堆的指针,都可以用相同的 Rust 的代码。也就是说,Rust 这边,它就认 C 的指针,而不管这个指针是从哪里来,栈也好,堆也好,甚至其它地址的指针也好,对 Rust 来说,其实都一样(本质上都是内存指针)。

  • 相关阅读:
    网络安全管理制度
    最近Intelli Idea官方2023
    算力免费,还奖钱,OpenI日常激励活动“我为开源打榜狂”来袭
    Dubbo 提供者与消费者的实现
    《硬件历险》之Mac抢救出现问题的时间机器硬盘中的数据
    CMT2380F32模块开发18-模拟电压比较器例程
    计算一个数的N次方,int和Integer的区别
    八股文--->并发编程
    H3C 6520X版本U盘升级
    leetcode做题笔记139. 单词拆分
  • 原文地址:https://blog.csdn.net/phthon1997/article/details/126732064