如何将盒装切片 (`Box<[T]>`) 传递给 C 函数?

Posted

技术标签:

【中文标题】如何将盒装切片 (`Box<[T]>`) 传递给 C 函数?【英文标题】:How to pass a boxed slice (`Box<[T]>`) to a C function? 【发布时间】:2017-01-12 20:50:47 【问题描述】:

我想向 C 函数公开一个“动态数组”。 C 函数将拥有数据,稍后将调用我的函数来释放数据。所以它看起来像下面这样:

fn get_something(len: *mut usize) -> *mut u8;
fn dealloc_something(data: *mut u8, len: usize);

在内部我有一个Box&lt;[T]&gt; (my_vec.to_boxed_slice())。我可以很容易地获得大小/长度,但我不知道应该返回哪个指针。如果我将从boxed_slice.as_mut_ptr() 返回的指针传递给Box::from_raw(),应用程序将崩溃。但是,如果我传递从 Box::into_raw 返回的指针,我无法找到内存布局的保证(指针指向数组的第一个元素,并且将在所有未来的 Rust 版本中继续这样做)。

这里有什么解决办法?

【问题讨论】:

【参考方案1】:

Box::into_raw 返回一个指向已分配存储开头的指针。切片是内存中连续的项目序列。因此,指针指向切片中的第一项。如果Box::into_raw 返回任何其他内容,它就不会真正有用。

boxed_slice.as_mut_ptr()Box::into_raw 之间的主要区别在于,Box::into_raw 获得了 box 的所有权但不释放它,而 boxed_slice.as_mut_ptr() 只是返回指针的副本并将 Box 的所有权留给您的函数,因此编译器会在返回之前隐式删除它。这意味着当您使用boxed_slice.as_mut_ptr() 时,您实际上是在返回一个指向已释放内存的指针!

【讨论】:

这意味着当你使用boxed_slice.as_mut_ptr()时,你实际上是在返回一个指向释放内存的指针...实际上我使用的是mem::forget,但这不是很重要。 你能把我链接到这种内存布局的参考吗? Box::into_raw 会返回指向第一个元素的指针吗?如果这是真的,我的问题得到了回答,我不需要再问任何其他问题了。 “切片是一个内存块的视图,表示为一个指针和一个长度。” doc。未指定切片数据的内存布局。您需要在切片上调用as_mut_ptr 以获取指向数据的有效指针。 @vinipsmaker:您可能想file an issue(如果还没有的话)要求澄清文档。

以上是关于如何将盒装切片 (`Box<[T]>`) 传递给 C 函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何克隆存储盒装特征对象的结构?

如何将 Rust `Vec<T>` 暴露给 FFI?

不能在 RedBean 中存储盒装模型?

如何从“盒子”中获得拥有的价值?

如何将 Integer.class (和其他盒装)转换为 int.class (和其他原语)?

Rust基础之理解Box<T>