首页 文章

如何将一个Rust`Vec <T>`暴露给FFI?

提问于
浏览
11

我正在尝试构造一对元素:

  • array: *mut T

  • array_len: usize

array 旨在拥有数据

但是,Box::into_raw将返回 *mut [T] . 我找不到有关将原始指针转换为切片的任何信息 . 它在内存中的布局是什么?我如何在C中使用它?我应该转换为 *mut T 吗?如果是这样,怎么样?

2 回答

  • 9

    如果你只是想让一些C函数可以相互借用 Vec ,你可以这样做:

    extern "C" {
        fn some_c_function(ptr: *mut i32, len: ffi::size_t);
    }
    
    fn safe_wrapper(a: &mut [i32]) {
        unsafe {
            some_c_function(a.as_mut_ptr(), a.len() as ffi::size_t);
        }
    }
    

    当然,C函数不应该将此指针存储在其他位置,因为这会破坏别名假设 .

    如果你想将数据“通过所有权”转换为C代码,你可以这样做:

    use std::mem;
    
    extern "C" {
        fn c_sink(ptr: *mut i32, len: ffi::size_t);
    }
    
    fn sink_wrapper(mut vec: Vec<i32>) {
        vec.shrink_to_fit();
        assert!(vec.len() == vec.capacity());
        let ptr = vec.as_mut_ptr();
        let len = vec.len();
        mem::forget(vec); // prevent deallocation in Rust
                          // The array is still there but no Rust object
                          // feels responsible. We only have ptr/len now
                          // to reach it.
        unsafe {
            c_sink(ptr, len as ffi::size_t);
        }
    }
    

    在这里,C函数“取得所有权”,我们希望它最终将指针和长度返回到Rust,例如,通过调用Rust函数来释放它:

    #[no_mangle]
    /// This is intended for the C code to call for deallocating the
    /// Rust-allocated i32 array.
    unsafe extern "C" fn deallocate_rust_buffer(ptr: *mut i32, len: ffi::size_t) {
        let len = len as usize;
        drop(Vec::from_raw_parts(ptr, len, len));
    }
    

    因为 Vec::from_raw_parts 需要三个参数,一个指针,一个大小和一个容量,我们要么必须以某种方式跟踪容量,要么在将指针和长度传递给C函数之前使用Vec的 shrink_to_fit . 但这可能涉及重新分配 .

  • 9

    您可以use [T]::as_mut_ptr直接从 Vec<T>Box<[T]> 或任何其他DerefMut到切片类型获取 *mut T 指针 .

    use std::mem;
    
    let mut boxed_slice: Box<[T]> = vector.into_boxed_slice();
    
    let array: *mut T = boxed_slice.as_mut_ptr();
    let array_len: usize = boxed_slice.len();
    
    // Prevent the slice from being destroyed (Leak the memory).
    mem::forget(boxed_slice);
    

相关问题