我试图构建一对元素:
array: *mut T
array_len: usize
array
旨在拥有这些数据
然而,Box::into_raw
将返回*mut [T]
.我找不到任何有关将原始指针转换为切片的信息.它在内存中的布局是什么?如何从C中使用它?我应该改成*mut T
吗?如果是,怎么做?
我试图构建一对元素:
array: *mut T
array_len: usize
array
旨在拥有这些数据
然而,Box::into_raw
将返回*mut [T]
.我找不到任何有关将原始指针转换为切片的信息.它在内存中的布局是什么?如何从C中使用它?我应该改成*mut T
吗?如果是,怎么做?
如果你只是想让一些C函数可变地borrow 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
.不过,这可能涉及重新分配.