I need to pass Vec
elements through FFI. While experimenting, I came across several interesting points. I started by providing FFI to all 3: ptr
, len
and capacity
, so that I can restore Vec
to destroy it later:
let ptr = vec.as_mut_ptr(); let len = vec.len(); let cap = vec.capacity(); mem::forget(vec); extern_fn(ptr, len, cap); // ... pub unsafe extern "C" fn free(ptr: *mut u8, len: usize, cap: usize) { let _ = Vec::from_raw_parts(ptr, len, cap); }
I wanted to get rid of capacity
, since it is useless for my interface; it’s just that I can recover my vector to free up memory.
Vec::shrink_to_fit()
is tempting because it seems to eliminate the need to deal with an ability. Unfortunately, the documentation on it does not guarantee that it will do len == capacity
, so I guess that from_raw_parts()
will most likely trigger Undefined Behavior.
into_boxed_slice()
seems to have a guarantee that it is going to make len == capacity
from docs , so I used this in the following. Please correct me if I am wrong . The problem is that it does not seem to guarantee redistribution. Here is a simple program:
fn main() { let mut v = Vec::with_capacity(1000); v.push(100u8); v.push(110); let ptr_1 = v.as_mut_ptr(); let mut boxed_slice = v.into_boxed_slice(); let ptr_2 = boxed_slice.as_mut_ptr(); let ptr_3 = Box::into_raw(boxed_slice); println!("{:?}. {:?}. {:?}", ptr_1, ptr_2, ptr_3); }
On the playground, he prints:
rustc 1.14.0 (e8a012324 2016-12-16) 0x7fdc9841b000. 0x7fdc98414018. 0x7fdc98414018
This is not good if he should find a new memory instead of getting rid of extra capacity without causing a copy.
Is there any other way to pass my vector through FFI (before C) and not skip the capacitance? It seems that into_boxed_slice()
is what I need, but why is it related to redistributing and copying data?