如何将Vec<T>转换为C友好的*mut T?

5
我有一个Rust库,通过FFI将数组返回给C调用者。该库还处理在客户端完成后删除数组。该库没有状态,因此客户端需要拥有该数组,直到将其传回库进行释放。
使用box::from_rawboxed::into_raw会很好,但我无法弄清如何将数组转换为返回类型。
1个回答

9

Vec<T>由三个值描述:

就 C 数组而言,容量是分配的内存大小,而长度则是实际包含在数组中的元素数量。两者都按 T 的数量计算。通常需要向 C 代码提供这三个值。

如果要使它们相等,可以使用.shrink_to_fit()来缩小向量的容量,尽可能接近其大小(具体取决于分配器)。

如果将 Vec<T> 的所有权还给 C 代码,请在检索到前面描述的 3 个值后调用 std::mem::forget(v),以避免其析构函数在函数结尾运行。

之后,可以使用from_raw_parts(..)从这三个值创建一个 Vec,如下所示:

let v = unsafe { Vec::<T>::from_raw_parts(ptr, length, capacity) };

当其析构函数运行时,内存将被正确释放。请注意,为了正确释放内存,这3个值需要正确。对于Vec<u8>来说并不是非常重要,但是Vec的析构函数将根据其length运行其包含的所有数据的析构函数。


2
你好,感谢您详细的回复。它帮助我找到了一个可接受的解决方案:为了从Vec<T>中获取一个C友好的指针(自包含),我使用了所述方法以及古老的C技巧,在数据前打包必要的元数据,并返回正确偏移量的指针给C调用者。通过反转该过程来丢弃内存。 - urubi
一个包含 Rust 函数分配数组并以 FFI 友好方式返回的代码示例将非常有帮助! - Johan Walles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接