简体   繁体   中英

How can I convert a Vec<T> into a C-friendly *mut T?

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:

  • 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM