如何将Rust'Vec< T>`暴露给FFI? [英] How to expose a Rust `Vec<T>` to FFI?

查看:73
本文介绍了如何将Rust'Vec< T>`暴露给FFI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to construct a pair of elements:

  • array: *mut T
  • array_len: usize
  • array: *mut T
  • array_len: usize

array用于拥有数据

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

However, Box::into_raw will return *mut [T]. I cannot find any info on converting raw pointers to slices. What is its layout in memory? How do I use it from C? Should I convert to *mut T? If so, how?

推荐答案

如果只希望某些C函数可变地借用Vec,则可以这样做:

If you just want some C function to mutably borrow the Vec, you can do it like this:

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函数不应将此指针存储在其他地方,因为这会破坏别名的假设.

Of course, the C function shouldn't store this pointer somewhere else because that would break aliasing assumptions.

如果要将数据的所有权传递给C代码,则可以执行以下操作:

If you want to "pass ownership" of the data to C code, you'd do something like this:

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函数来取消分配它:

Here, the C function "takes ownership" in the sense that we expect it to eventually return the pointer and length to Rust, for example, by calling a Rust function to deallocate it:

#[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 .不过,这可能涉及重新分配.

Because Vec::from_raw_parts expects three parameters, a pointer, a size and a capacity, we either have to keep track of the capacity as well somehow, or we use Vec's shrink_to_fit before passing the pointer and length to the C function. This might involve a reallocation, though.

这篇关于如何将Rust'Vec&lt; T&gt;`暴露给FFI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆