我正尝试构建一对元素:
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
?如果是这样,如何转换?
如果你只想要一些用于可变借用 Vec
的 C 函数,你可以这样做:
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
。但这可能涉及重新分配内存。
[T]::as_mut_ptr
直接从Vec<T>
、Box<[T]>
或任何其他DerefMut-to-slice类型中获取*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);
into_boxed_slice
会返回什么内存布局?boxed_slice.as_mut_ptr()
保证返回指向第一个字符的指针吗?我该如何转换回Box<[T]>
以便进行解除分配? - vinipsmaker(ptr,len)
。(2)也许你应该提出一个新问题。但你可以尝试使用slice::from_raw_parts_mut
和Box::from_raw
,或者使用Vec::from_raw_parts
,但你需要传递容量。 - kennytmslice::from_raw_parts
+ Box::from_raw
在这里可以吗?Box::from_raw
不是获取指向栈分配的切片的指针而不是原始切片吗?或者 Box<[T]>
是一个特殊情况? - vinipsmakerslice::from_raw_parts_mut(array, array_len)
的结果将引用你的堆分配内存。在这里,没有涉及任何数组的堆栈分配。而 Box::from_raw
将再次拥有它,因此在它被丢弃时,它将被适当地释放。但是,所有这些基本上都归结为 Vec::from_raw_parts(array, array_len, array_len)
,向 vec 再次转移了拥有权。顺便说一下:在这里使用 into_boxed_slice
是很重要的,因为它会减小容量以匹配大小。否则,你还需要记住原始容量。 - sellibitze
assert!
之外,我还在考虑使用它,但我不够自信/说服。 - vinipsmaker.as_mut_ptr()
操作,它会返回0x1
(即无效指针)。 - Brandon RosVec::shrink_to_fit
的文档表明,你的断言assert!(vec.len() == vec.capacity());
并不总是正确的(文档只断言capacity() >= len()
)。这个问题 本质上涉及到了同样的问题,因此我在那里提到了这个答案,但该问题具体涉及到shrink_to_fit
不精确的可能性,这似乎没有在这里得到解决,但似乎也与此相关。 - kaya3