How can I convert a Vec<T> into a C-friendly *mut T?
ffi, rust
Solution
A `Vec<T>` is described by 3 values:
- A pointer to its first element, that can be obtained with `.as_mut_ptr()`
- A length, that can be obtained with `.len()`
- A capacity, that can be obtained with `.capacity()`
In terms of a C array, the capacity is the size of memory allocated, while the length is the number of elements actually contained in the array. Both are counting in number of `T`. You normally would need to provide these 3 values to your C code.
If you want them to be equals, you can use `.shrink_to_fit()` on the vector to reduce its capacity as near as its size as possible depending on the allocator.
If you give back the ownership of the `Vec<T>` to your C code, don't forget to call `std::mem::forget(v)` on it once you have retrieved the 3 values described before, to avoid having its destructor running at the end of the function.
Afterwards, you can create back a `Vec` from these 3 values using `from_raw_parts(..)` like this:
let v = unsafe { Vec::<T>::from_raw_parts(ptr, length, capacity) };
and when its destructor will run the memory will be correctly freed. Be careful, the 3 values need to be correct for deallocation of memory to be correct. It's not very important for a `Vec<u8>`, but the destructor of `Vec` will run the destructor of all data it contains according to its `length`.
Problem
I have a Rust library that returns a `u8` array to a C caller via FFI. The library also handles dropping the array after the client is done with it. The library has no state, so the client needs to own the array until it is passed back to the library for freeing. Using `box::from_raw` and `boxed::into_raw` would be nice, but I couldn't manage to work out how to convert the array into the return type.