I'm trying to construct a pair of elements:
array: *mut T
array_len: usize
array
is intended to own the data
However, Box::into_raw
will return *mut [T]
. I cannot find any info on converting raw pointers to slices. What is its layout in memory? How do I use it from C? Should I convert to *mut T
? If so, how?
To remove all elements from a vector in Rust, use . retain() method to keep all elements the do not match. let mut v = vec![
In Rust, there are several ways to initialize a vector. In order to initialize a vector via the new() method call, we use the double colon operator: let mut vec = Vec::new();
Vector is a module in Rust that provides the container space to store values. It is a contiguous resizable array type, with heap-allocated contents. It is denoted by Vec<T>. Vectors in Rust have O(1) indexing and push and pop operations in vector also take O(1) complexity.
If you just want some C function to mutably borrow the Vec
, you can do it like this:
extern "C" { fn some_c_function(ptr: *mut i32, len: ffi::size_t); } fn safe_wrapper(a: &mut [i32]) { unsafe { some_c_function(a.as_mut_ptr(), a.len() as ffi::size_t); } }
Of course, the C function shouldn't store this pointer somewhere else because that would break aliasing assumptions.
If you want to "pass ownership" of the data to C code, you'd do something like this:
use std::mem; extern "C" { fn c_sink(ptr: *mut i32, len: ffi::size_t); } fn sink_wrapper(mut vec: Vec<i32>) { vec.shrink_to_fit(); assert!(vec.len() == vec.capacity()); let ptr = vec.as_mut_ptr(); let len = vec.len(); mem::forget(vec); // prevent deallocation in Rust // The array is still there but no Rust object // feels responsible. We only have ptr/len now // to reach it. unsafe { c_sink(ptr, len as ffi::size_t); } }
Here, the C function "takes ownership" in the sense that we expect it to eventually return the pointer and length to Rust, for example, by calling a Rust function to deallocate it:
#[no_mangle] /// This is intended for the C code to call for deallocating the /// Rust-allocated i32 array. unsafe extern "C" fn deallocate_rust_buffer(ptr: *mut i32, len: ffi::size_t) { let len = len as usize; drop(Vec::from_raw_parts(ptr, len, len)); }
Because Vec::from_raw_parts
expects three parameters, a pointer, a size and a capacity, we either have to keep track of the capacity as well somehow, or we use Vec's shrink_to_fit
before passing the pointer and length to the C function. This might involve a reallocation, though.
You could use [T]::as_mut_ptr
to obtain the *mut T
pointer directly from Vec<T>
, Box<[T]>
or any other DerefMut-to-slice types.
use std::mem; let mut boxed_slice: Box<[T]> = vector.into_boxed_slice(); let array: *mut T = boxed_slice.as_mut_ptr(); let array_len: usize = boxed_slice.len(); // Prevent the slice from being destroyed (Leak the memory). mem::forget(boxed_slice);
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