I have a Rust function that returns an array
and I want to use this array in Python
, it could be a list
or numpy.array
it does not really matter.
My Rust function looks like this:
#[no_mangle]
pub extern fn make_array() -> [i32; 4] {
let my_array: [i32; 4] = [1,2,3,4];
return my_array;
}
And I am trying to call it in Python like this:
In [20]: import ctypes
In [21]: from ctypes import cdll
In [22]: lib = cdll.LoadLibrary("/home/user/RustStuff/embed/target/release/libembed.so")
In [23]: lib.make_array.restype = ctypes.ARRAY(ctypes.c_int32, 4)
In [24]: temp = lib.make_array()
In [25]: [i for i in temp]
Out[25]: [1, 2, -760202930, 32611]
What am I doing wrong? Why is my output not [1,2,3,4]
? Why are my first two elements right and other two are populated with garbage?
I was not able to find any good documentation on ctypes.ARRAY
, so I just went with what looked right, so that is likely the problem.
As others have said, you can't really return a fixed-size array properly. But you can trick ctypes into doing the right thing by wrapping the array in a structure:
This results in
[1, 2, 3, 4]
on my machine.Addendum: This is a "trick" because we're exploiting a difference between what C can do and what Rust can do. C won't let you return a fixed-sized array by value, but Rust will, and it works the same as returning a user-defined structure.
So, we do something that C will allow: returning a structure which happens to contain a fixed-size array. This, it is fine with, and it matches the layout that Rust is using.
Of course, this is also somewhat hacky, in that I'm not entirely convinced that this is well-defined behaviour. If you want to be extra safe, you could change the return type on the Rust side to match C: