The C library call expects the caller to take ownership of the 6 doubles and delete them at some point. I'd like to create a higher-level Rust function that hides the details of the FFI call and returns the doubles in a Vec.
Is the following (admittedly clunky) attempt an idiomatic way of going about this in Rust?
pub fn coeffs() -> Vec<f64> {
let mut result = Vec::with_capacity(6);
unsafe {
let values = raw_coeffs();
result.set_len(6);
values.copy_to_nonoverlapping(result.as_mut_ptr(), 6);
std::ptr::drop_in_place(values);
result
}
}
I don't think drop_in_place is supposed to be used on memory allocated by C-Code. C is going to use the C system allocator and Rust may or may not be using the system allocator (by default Rust does not and instead uses jemalloc). to safely deallocate (free) a pointer to memory allocated by C-Code requires that you call the C "free" function.
Rust's drop-related functionality is strictly only for values created by Rust itself. Don't use it on a pointer from C.
To free the data behind the C pointer you should call a C function that does it, so that definitely the same C's allocator is used. If the pointer comes from C's malloc, then Rust's libc::free may work, except it's dangerous to do so if Windows DLLs are involved, since each DLL may have separate runtime.
Don't use unsafe set_len. You can use a safe loop with push() — it optimizes well.
You can cast *mut f64 to *mut [f64; 6] if you know there are certainly 6 items there (or std::slice::from_raw_parts() if the length was dynamic).
From there you can use .as_ref().unwrap() to make it a reference, and then .to_owned() or vec.extend(&arr) to copy it to a Vec.
Seems odd to allocate an array for 6 doubles. Perhaps have the C code take an array from the caller and populate it. Rust can then send a stack allocated array via FFI and nothing needs to be explicitly freed on the C side. Or you can send Rust heap allocated storage and let Rust free it normally.