美文网首页
C++与Rust操作裸指针的比较

C++与Rust操作裸指针的比较

作者: 熊皮皮 | 来源:发表于2018-11-09 07:29 被阅读154次

    文档列表见:Rust 移动端跨平台复杂图形渲染项目开发总结 - 目录

    判断指针是否为NULL/nullptr

    假设存在const T* ptr1T* ptr2,分别判断它们是否为空,C++和Rust实现如下所示。

    if ((NULL == ptr1) || (nullptr == ptr2)) {
      // do something
    }
    
    use std::ptr;
    
    if ptr::null() == ptr1 || ptr::null_mut() == ptr2 {
        // do something
    }
    

    返回nullptr/NULL

    由前面可知,Rust提供C接口时返回nullptr或NULL的实现如下

    #[no_mangle]
    pub extern "C" fn init_engine() -> * const c_void {
        // something goes wrong
        std::ptr::null()
    }
    
    fn main() {
        unsafe{
            let engine = init_engine();
            println!("{:?}", engine);
        }
    }
    

    使用slice直接读写指针内容

    写指针

    const int COUNT = 100;
    int *int_ptr = new int[COUNT];
    for (int i = 0; i < COUNT; ++i) {
        int_ptr[i] = i;
    }
    

    将上述C++申请的ptr指针传递到Rust进行写入,最差的办法是在Rust内部创建一个长度相同的Vector,将数据写入Vector,再通过std::ptr::copyint_ptr中,示例如下:

    use std::ptr;
    
    #[no_mangle]
    pub extern "C" fn write_to_c_buffers(n: usize, buffers: *mut i32) {
        let mut tmp_buffers = Vec::with_capacity(n);
        for index in 0..n {
            tmp_buffers.push(index);
        }
        unsafe {
            ptr::copy(tmp_buffers.as_ptr(), buffers, n);
        }
    }
    

    上述的tmp_buffers分配了一块与buffers等长的新内存,这样多占用了内存,不科学。

    使用std::slice直接读写裸指针可实现前面C++式的做法,示例如下:

    use std::slice;
    
    #[no_mangle]
    pub extern "C" fn write_to_c_buffers(n: usize, buffers: *mut i32) {
        unsafe {
            let mut slice = slice::from_raw_parts_mut(buffers, n);
            for index in 0..n {
                slice[index] = index; 
            }
        }
    }
    

    进一步,可使用Rust类似C#的foreach进行循环,同时缩小unsafe代码块的影响空间。读指针也可用这个方案。

    use std::slice;
    
    #[no_mangle]
    pub extern "C" fn write_to_c_buffers(n: usize, buffers: *mut i32) {
      let mut buffers = unsafe { slice::from_raw_parts_mut(buffers, n) };
      for slice in buffers {
        *slice = //do something; 
      }  
    }
    

    读指针

    int summary(size_t count, int ptr*) {
        int sum = 0;
        for (int i = 0; i < count; ++i) {
            sum += ptr[i];
        }
        return sum;
    }
    

    ptr传递到Rust进行求和,用slice可以直接操作,避免分配额外的内存,示例如下:

    use std::slice;
    
    #[no_mangle]
    pub extern "C" fn summary_for_c_buffers(n: usize, buffers: *const i32) {
        unsafe {
            let slice = slice::from_raw_parts(buffers, n);
            let mut sum = 0;
            for index in 0..n {
                sum += slice[index];
            }
            sum
        }
    }
    

    相关文章

      网友评论

          本文标题:C++与Rust操作裸指针的比较

          本文链接:https://www.haomeiwen.com/subject/rlhnxqtx.html