我正在尝试构建一对元素:
array: *mut T
array_len: usize
array
旨在拥有数据
但是,Box::into_raw
将返回*mut [T]
。我找不到有关将原始指针转换为切片的任何信息。它在内存中的布局是什么?我如何在C中使用它?我应该转换为*mut T
吗?如果是这样,怎么样?
答案 0 :(得分:11)
如果你只是想让一些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
需要三个参数,一个指针,一个大小和一个容量,我们要么必须以某种方式跟踪容量,要么我们在传递指针和长度之前使用Vec的shrink_to_fit
到C函数。但这可能涉及重新分配。
答案 1 :(得分:9)
您可以use [T]::as_mut_ptr
直接从*mut T
,Vec<T>
或任何其他DerefMut到切片类型获取Box<[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);