• Rust-FFI复杂参数传递处理方式1--数组类型


    预先知识点

    1.FFI (Foreign Function Interface) 是 Rust 中非常重要的一个部分,它主要在两个领域应用较广泛:
    第一个是系统开发,这部分包括对 OS 系统调用的封装,对系统底层 C 库的封装,广泛平台的嵌入式/IoT 开发,OS 开发,充分利用现代硬件平台的性能优势。
    第二个是跨语言开发,可以使用 Rust 语言为其它(几乎任何)语言写调用库,互相调用等。
    利用 FFI,Rust 终能迅速切入巨大的存量遗产,同时也能牢牢把握新兴增量领域。螃蟹怎么横着走?就是有了FFI。

    2.C语言和Rust的相互调用,最核心的就是指针的操作,两边的代码使用的是同一个程序栈,栈上的指针能放心地传递,而不用担心被错误释放的问题(栈上内存被调用规则自动管理,C和Rust中都是如此)。两边的代码可能使用不同的堆分配器,因此,堆上的指针的传递需要严格注意,需要各自管理各自的资源,谁创建谁释放,指针传递过程中,需要分析所有权问题。栈和堆的操作是不同的,这里一定要注意。

    复杂参数传递处理方式1–数组类型

    前面两个例子是最简单的整型类型的参数传递,能说明 Rust 导出共享库的基本模板操作,但在函数参数这块儿,能说明的问题有限。
    C调用Rust,传入一个数组并返回一个求和之后的数。
    C语言代码:

    #include 
    #include 
     
    extern uint32_t sum_of_array(const uint32_t *numbers, size_t length);
     
    int main(void) {
      uint32_t numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
      unsigned int length = sizeof(numbers) / sizeof(*numbers);
      uint32_t sum = sum_of_array(numbers, length);
      printf("print in c, sum is: %d\n", sum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Rust代码:

    use std::slice;
     
    #[no_mangle]
    pub extern "C" fn sum_of_array(array: *const u32, len: usize) -> u32 {
        let array = unsafe {
            assert!(!array.is_null());
            slice::from_raw_parts(array, len)
        };
       array.iter().sum()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    对上面的代码解读:
    1.对于数组的传递,分成了两个部分,一个是数组地址指针的传递(首元素指针),另一个是数组的长度(即元素的个数,非字节数)。
    2.对于C语言中,数组是分配在栈上的,Rust 代码中,参数中的 *const u32 就对应 C 中的 const uint32_t *。
    3.C语言传入的指针,Rust必须保证是绝对不能为空指针的,所以使用assert进行捕获。
    4.slice::from_raw_parts(array,len)的作用是从一个指针和一个长度形成一个切片,长度还是元素的个数。这里的array就是切片类型了。
    5.Rust 拿到 C 传递过来的指针后,标准的规范是:
    尽早转换为 Rust 的安全类型进行操作。也就是说,保证不安全(unsafe块中的)的代码尽量少,并且直接使用这个指针的代码尽可能的少,转换成 Rust 中的标准类型再用。
    尽量保证 zero cost。避免不必要的内存 copy 操作,影响性能。
    为满足第一条规则,在转换前,我们的代码没有任何相关的代码。
    为满足第二条规则,这里使用了 slice 类型,而不是 Vec 类型,slice切片属于部分引用,而vec属于堆分配部分的使用,会进行内存copy。

  • 相关阅读:
    关于tensorboard无法打开
    新体验经济@2022: 世界杯、啤酒与供应链
    C++对象
    Spring框架(缺SM整合)
    springboot + mybatis
    JavaScript算法之旅:简易桶排序、冒泡排序、快速排序
    快速了解常用的对称加密算法,再也不用担心面试官的刨根问底
    Service层代码单元测试以及单元测试如何Mock
    【Linux】—— 详解动态库和静态库
    阿里云2023年双十一优惠活动整理
  • 原文地址:https://blog.csdn.net/phthon1997/article/details/126620044