我有一个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上找不到任何好的文档,所以我只 Select 了看起来正确的,所以这可能是问题所在.

推荐答案

正如其他人所说,不能正确返回固定大小的array.但是,通过将数组包装到一个 struct 中,可以让trick个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]个.

Addendum:这是一个"把戏",因为我们正在利用C和Rust之间的差异.Cwon't允许您按值返回一个固定大小的数组,但其工作原理与返回用户定义的 struct 相同.

所以,我们做了一些Cwill允许的事情:返回一个碰巧包含固定大小数组的 struct .这一点很好,并且与Rust使用的布局相匹配.

当然,这也有点骇人听闻,因为我不相信这是定义明确的行为.如果你想更加安全,你可以改变Rust 一侧的返回类型,使其与C匹配:

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

Rust相关问答推荐

为什么我的梅森素数代码的指数越大,速度就越快?

无法在线程之间安全地发送future (&Q;)&错误

如何导出 rust 色二进制文件中的符号

这种获取-释放关系是如何运作的?

当第二个`let`依赖于第一个`let()`时,如何在一行中有多个`let()`?

异步FN中的 rust 递归

为什么这是&q;,而让&q;循环是无限循环?

为什么比较Option<;字符串>;具有常数Option<&;str>;需要显式类型转换吗?

为什么 tokio 在以奇怪的方式调用时只运行 n 个任务中的 n-1 个?

如何重命名 clap_derive 中的子命令占位符?

使用 pyo3 将 Rust 转换为 Python 自定义类型

Rust Axum 框架 - 解包安全吗?

Rust Option 的空显式泛型参数

需要一个有序向量来进行 struct 初始化

闭包返回类型的生命周期规范

简单 TCP 服务器的连接由对等重置错误,mio 负载较小

按下 Ctrl + C 时优雅地停止命令并退出进程

如何在 Rust 中创建最后一个元素是可变长度数组的 struct ?

以下打印数组每个元素的 Rust 代码有什么问题?

如何在 Rust 的内置函数上实现特征?