How to pass a boxed slice (`Box<[T]>`) to a C f

2019-08-06 13:53发布

问题:

I want to expose a "dynamic array" to a C function. The C function will own the data and later will call a function of mine to free the data. So it'll look something like the following:

fn get_something(len: *mut usize) -> *mut u8;
fn dealloc_something(data: *mut u8, len: usize);

Internally I have a Box<[T]> (my_vec.to_boxed_slice()). I can get the size/length pretty easily, but I don't know which pointer I should return. If I pass the pointer returned from boxed_slice.as_mut_ptr() to Box::from_raw(), the application crashes. However, if I pass the pointer returned from Box::into_raw, I can't find a guarantee of memory layout (the pointer points to the first element of the array and will continue to do so for all future Rust versions).

What's the solution here?

回答1:

Box::into_raw returns a pointer to the beginning of the allocated storage. A slice is a contiguous sequence of items in memory. Therefore, the pointer points to the first item in the slice. If Box::into_raw returned anything else, it wouldn't be really useful.

The main difference between boxed_slice.as_mut_ptr() and Box::into_raw is that Box::into_raw takes ownership of the box but does not deallocate it, while boxed_slice.as_mut_ptr() just returns a copy of the pointer and leaves ownership of the Box to your function, so the compiler implicitly drops it before returning. This means that when you use boxed_slice.as_mut_ptr(), you are essentially returning a pointer to freed memory!