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

标签 python rust ctypes

我有一个返回 array 的 Rust 函数,我想在 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]
}

关于python - 使用 ctypes 在 Python 中使用 Rust 返回的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30966886/

相关文章:

rust - 访问由 Take 或 Chain 包装的 Read 组件

arrays - 将字符串数组传递给函数而无需指定 N(编译时间常数)

python - python在哪里寻找ctypes.cdll.<name>在windows上打开的dll?

python - Ctypes:分配 double** ,将其传递给 C,然后在 Python 中使用

c - Python Ctypes OSError : exception: access violation reading 0x00000000

python - Dask 和 Numba - 如何有效地使用 map 分区?

python - numpy - Python - 有选择地导入 .txt 文件的部分内容

Python 程序没有按预期提示用户

python - 格式化/抑制 Pandas 聚合结果的科学记数法

rust - 如何才能让 Future Producer 至少达到 rust rdkafka 中 Threaded Producer 的性能?