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.
A Vec<T>
is described by 3 values:
.as_mut_ptr()
.len()
.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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With