繁体   English   中英

使用 ctypes 在 Python 中使用 Rust 返回的数组

[英]Using Rust returned array in Python using ctypes

我有一个 Rust 函数,它返回一个array ,我想在Python使用这个数组,它可以是一个listnumpy.array它并不重要。

我的 Rust 函数如下所示:

#[no_mangle]
pub extern fn make_array() -> [i32; 4] {
    let my_array: [i32; 4] = [1,2,3,4];
    return my_array;
}

我试图在 Python 中像这样调用它:

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] 为什么我的前两个元素是正确的,而另外两个是垃圾?

我找不到关于ctypes.ARRAY任何好的文档,所以我只选择了看起来正确的东西,所以这可能是问题所在。

正如其他人所说,您无法真正正确返回固定大小的数组。 但是你可以通过将数组包装在一个结构中来欺骗ctypes 做正确的事情:

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]

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

所以,我们做的东西是c将使:返回恰好包含一个固定大小的数组结构。 这很好,并且与 Rust 使用的布局相匹配。

当然,这也有点老套,因为我并不完全相信这是定义明确的行为。 如果你想更加安全,你可以改变 Rust 端的返回类型以匹配 C:

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

我同意@delnan所说的 -你不能在 C 中返回固定大小的数组 一个主要的不兼容性是 Rust 数组知道它们的大小,但 C 数组不知道。 您将需要遵守其他每个 C 程序如何做到这一点 - 分别返回一个指针和一个长度。 相比之下,Rust 难道不是一种很好的现代语言吗?

从另一个答案中窃取并修改了一些 Python 代码

import ctypes

from ctypes import cdll

lib = cdll.LoadLibrary("libarray.dylib")
lib.make_array.restype = ctypes.POINTER(ctypes.c_int32 * 4)

print [i for i in lib.make_array().contents]

这适用于这个 Rust 代码:

static ARRAY: [i32; 4] = [1,2,3,4];

#[no_mangle]
pub extern fn make_array() -> *const i32 {
    ARRAY.as_ptr()
}

在这里,我们正在做最简单的事情,创建一个数组,该数组将在程序的整个长度内有效,并返回对其数据的引用。 在您的实际程序中,您可能需要更加小心以确保您的Vec<i32>&[i32]严格超过 Python 代码具有指针的时间,否则您将导致内存损坏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM