I'm trying to use FFI to generate payload in a dynamic length buffer, and pass the ownership to the caller.
struct CustomAlloc(Global);
unsafe impl Allocator for CustomAlloc {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
println!("allocating");
self.0.allocate(layout)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
print!("deallocating");
self.0.deallocate(ptr, layout)
}
}
// generate a boxed slice with payload, pass ownership to caller and released by called
unsafe fn ffi(ptr: &mut *mut [u8]) {
println!("in ffi: input ptr is {:p}", *ptr);
let size = 100usize;
let mut boxed_slice = Box::new_zeroed_slice_in(size, CustomAlloc(Global));
boxed_slice.iter_mut().for_each(|i| {
i.write(15u8);
});
let boxed_slice = boxed_slice.assume_init();
*ptr = Box::into_raw(boxed_slice);
println!("in ffi: input ptr is {:p}", *ptr);
}
fn unsafe_codes() {
let mut p_slice: *mut [u8] = unsafe { slice::from_raw_parts_mut(std::ptr::null_mut(), 0) };
let pp_slice = &mut p_slice;
unsafe {
ffi(pp_slice);
}
let boxed_slice = unsafe { Box::from_raw_in(p_slice, CustomAlloc(Global)) };
println!("{:?}", &*boxed_slice);
}
I use Box to transfer the ownership, so that the boxed_slice
doesn't need to call another ffi to release the buffer. But the p_slice
seems not created in a nice way [ MIRI tells it is UB?].
Is there any better way for this situation?
Update 1:
Maybe passing &mut *mut u8
and &mut usize
is a better chioce?
unsafe fn ffi_x(ptr: &mut *mut u8, len: &mut usize) {
println!("in ffi_x: input ptr is {:p}", *ptr);
*len = 100usize;
let mut boxed_slice = Box::new_zeroed_slice_in(*len, CustomAlloc(Global));
boxed_slice.iter_mut().for_each(|i| {
i.write(10u8);
});
*ptr = Box::into_raw(boxed_slice.assume_init()).as_mut_ptr();
println!("in ffi: input ptr is {:p}", *ptr);
}
unsafe fn unsafe_codes_x() {
let mut ptr = ptr::null_mut();
let pptr = &mut ptr;
let mut len = 0usize;
unsafe { ffi_x(pptr, &mut len) }
let slice = slice::from_raw_parts_mut(ptr, len);
let boxed_slice = Box::from_raw_in(slice, CustomAlloc(Global));
println!("{:?}", &*boxed_slice);
}