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

C语言代码:

// csrc/cfoo1.c
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
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);
}

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
实践2

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

// csrc/cfoo2.c
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
 
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.这里的传递方式和上面还是一样的,只是这里的C语言部分,自己做了个申请,,定义了一个返回结构体指针的函数,这边的堆释放需要手动完成。

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值