如何将Rust'Vec< T>`暴露给FFI? [英] How to expose a Rust `Vec<T>` to 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< T>`暴露给FFI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!