使用ctypes在Python中使用Rust返回的数组 [英] Using Rust returned array in Python using ctypes

查看:128
本文介绍了使用ctypes在Python中使用Rust返回的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Rust函数,它返回一个 array ,并且我想在 Python 中使用该数组,是列表 numpy.array 都没关系。

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.

我的Rust函数如下:

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;
}

我想在Python中这样称呼它:

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]

什么我做错了吗?为什么我的输出不是 [1,2,3,4] ?为什么我的前两个元素正确,而其他两个元素都充满了垃圾?

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?

我找不到关于 ctypes.ARRAY ,所以我只看了正确的内容,所以可能是问题所在。

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.

推荐答案

曾经说过,您真的不能正确返回固定大小的数组。但是您可以通过将数组包装在结构中来欺骗 ctypes以执行正确的操作:

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:

import ctypes

class Int32_4(ctypes.Structure):
    _fields_ = [("array", ctypes.c_int32 * 4)]

lib = ctypes.CDLL("embed.dll")
lib.make_array.restype = Int32_4

temp = lib.make_array()

print(temp.array[:])

结果为 [1、2、3、4] 在我的计算机上。

This results in [1, 2, 3, 4] on my machine.

附录:这是一个技巧,因为我们正在利用C可以做什么和Rust可以做什么。 C 不会让您按值返回固定大小的数组,但是Rust ,并且其作用与返回用户定义的结构相同。

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.

因此,我们做了C 允许的操作:返回恰好包含固定大小的数组的结构。

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.

当然,这也有点hacky,因为我不是完全确信这是明确定义的行为。如果您想更加安全,可以在Rust一侧更改返回类型以匹配C:

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:

#[repr(C)]
struct Int32_4 {
    array: [i32; 4]
}

这篇关于使用ctypes在Python中使用Rust返回的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆