I want to return a f64 vector from Rust to Python and I'm not sure how to dereference the returned pointer in Python side.
lib.rs
use libc::c_double;
#[no_mangle]
pub extern "C" fn give_me_array() -> *const Vec<c_double> {
let array_to_pass = vec![1.05, 1.07, 2.48]; // Just an example... there are some calculations here
&array_to_pass
}
requesting_array.py
from cffi import FFI
ffi = FFI()
ffi.cdef("""
double* give_me_array();
""")
dll = ffi.dlopen("...path_to_dll...")
returned_array = dll.give_me_array()
print(returned_array)
The output is a memory location:
<cdata 'double *' 0x00000....>
Expected output: 1.05, 1.07, 2.48
How to dereference the array in the python side? Is this the best approach to pass a variable sized vector from Rust to Python?
Rust-side solution by Aiden4 and modifications on Python side
lib.rs
use libc; // 0.2.93
#[repr(C)]
pub struct CDoubleArray {
pub ptr: *mut libc::c_double,
pub len: usize,
}
#[no_mangle]
pub extern "C" fn give_me_array() -> CDoubleArray {
let vec = vec![1.05, 1.07, 2.48];
let len = vec.len();
CDoubleArray {
ptr: vec.leak().as_mut_ptr(), //leaked so the caller is responsible for the memory
len,
}
}
#[no_mangle]
pub unsafe extern "C" fn free_array(arr: CDoubleArray) {
// since the caller is responsible for the memory we have to provide a way to free it
Vec::from_raw_parts(arr.ptr, arr.len, arr.len);
}
requesting_array.py
from cffi import FFI
ffi = FFI()
ffi.cdef("""
typedef struct {
double *v2_ptr;
unsigned long v2_size;
} CDoubleArray;
CDoubleArray give_me_array();
void free_array(CDoubleArray);
""")
dll = ffi.dlopen("...path_to.dll...")
returned_array = ffi.new("CDoubleArray *")
returned_array = dll.give_me_array()
for n in range(returned_array.v2_size):
print(returned_array.v2_ptr[n])