当前位置: 首页 > 面试题库 >

将Python列表传递给嵌入式Rust函数

厍光霁
2023-03-14
问题内容

我正在学习如何在Python中嵌入Rust函数,并且如果我的输入是ints而不是list ,一切都可以正常工作。

如果我的lib.rs文件是:

#[no_mangle]
pub extern fn my_func(x: i32, y: i32) -> i32 {
    return x + y;
}

我可以这样使用:

In [1]: from ctypes import cdll

In [2]: lib = cdll.LoadLibrary("/home/user/RustStuff/embed/target/release/libembed.so")

In [3]: lib.my_func(5,6)
Out[3]: 11

但是,如果我更改lib.rs为:

#[no_mangle]
pub extern fn my_func(my_vec: Vec<i32>) -> i32 {
    let mut my_sum = 0;
    for i in my_vec {
        my_sum += i;
    }
    return my_sum;
}

我不能再在Python中使用它(此编译良好):

In [1]: from ctypes import cdll

In [2]: lib = cdll.LoadLibrary("/home/user/RustStuff/embed/target/release/libembed.so")

In [3]: lib.my_func([2,3,4])
---------------------------------------------------------------------------
ArgumentError                             Traceback (most recent call last)
<ipython-input-3-454ffc5ba9dd> in <module>()
----> 1 lib.my_func([2,3,4])

ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how to convert parameter 1

原因,尽管我可以这样做是因为Pythonlist和RustVec都是 动态数组 ,但显然我在这里缺少了一些东西。

为什么我的尝试不起作用?我该怎么做才能解决?


问题答案:

不要这样做:

#[no_mangle]
pub extern fn my_func(my_vec: Vec<i32>) -> i32 { ... }

基本上,您 从不 希望接受或返回extern函数中的任意Rust对象,仅是Repr。相反,您应该接受C可以表示的内容。正如6502所说的,对于这种特殊情况,最好的主意是接受一个指针和一个长度。

Vec从概念上讲,Rust的指针指向数据,计数 html" target="_blank">容量
。您可以Vec通过添加或删除对象来修改,这可能导致重新分配。这是双重不利的,因为Python和Rust可能使用彼此不兼容的不同分配器。分段错误就是这样!你真的想要
切片

相反,在Rust方面执行以下操作:

extern crate libc;

use libc::{size_t,int32_t};
use std::slice;

#[no_mangle]
pub extern fn my_func(data: *const int32_t, length: size_t) -> int32_t {
    let nums = unsafe { slice::from_raw_parts(data, length as usize) };
    nums.iter().fold(0, |acc, i| acc + i)
}

也就是说,您正在使用保证匹配的C类型,然后将指针和长度转换为Rust知道如何处理的东西。

我不是Pythonista,但是这个经过拼凑的代码(在“如何使用ctypes将Python列表转换为C数组?”的帮助下)似乎可以与上面的Rust一起使用:

import ctypes

lib = ctypes.cdll.LoadLibrary("./target/debug/libpython.dylib")
lib.my_func.argtypes = (ctypes.POINTER(ctypes.c_int32), ctypes.c_size_t)

list_to_sum = [1,2,3,4]
c_array = (ctypes.c_int32 * len(list_to_sum))(*list_to_sum)
print lib.my_func(c_array, len(list_to_sum))

当然,您可能希望将其包装起来以使其对您的代码调用者更好。



 类似资料:
  • 问题内容: 我想按值将列表传递给函数。默认情况下,列表和其他复杂对象通过引用传递给函数。这是一些目标: 可以写得短些吗?换句话说,我不想更改 ad 。 问题答案: 您可以使用,但是对于包含列表(或其他可变对象)的列表,您应该使用: 等价于或,并返回列表的浅表副本。 何时使用:

  • 问题内容: 这是我的代码: 当我评估f(0)时,将出现错误“ x在分配之前被引用”。 但是,当我使用“ print x”代替“ x = x + 1”时,它将起作用。 似乎在g的范围内,我只能将x用作“使用事件”,而不能用作“绑定事件”。我想问题是f仅将x的值传递给g。 我是否正确理解?如果不是,有人可以解释为什么在引用之前未定义“ x = x + 1”的左侧吗? 谢谢 问题答案: 您正确理解了它。

  • 问题内容: 当提供一些参数时,我想使我的python脚本从命令行运行。但是,参数之一应该是特定于脚本一个片段的选项列表。字符串解析是在逗号分隔“命令行列表”字符串之后实际构造列表的唯一方法吗?如果是这样,您将如何处理? 示例:-details = [‘name’,’title’,’address’] 问题答案: 程序: 命令行: 输出: 此代码段将执行短或长命令切换(例如或),并在切换到Pytho

  • 问题内容: 我的字符串中某些地方包含数字,并且我正尝试用其单词符号替换此数字(即3-> 3)。我有一个功能可以做到这一点。现在的问题是找到字符串中的数字,同时保持字符串的其余部分不变。为此,我选择使用该函数,该函数可以接受“ callable”。但是,传递给它的对象是内部对象,我不确定如何处理它。我的函数接受数字或其字符串表示形式。 我应该如何编写一些辅助函数,该函数可用于将调用与执行所需处理的函

  • 问题内容: 我正在尝试从SQL导出到.csv,如果我对其进行硬编码以接受一定数量的参数,则它可以正常工作。问题是,我想允许用户请求任意数量的参数,并将它们传递给where子句。该代码应该使这一点更加清楚。 所以我想我要做的是将列表传递给where子句,而不是显式的:dates#变量。例如,一个人可以使用参数“ 2012-01-0412:00、2012-02-04 12:00、2012-03-04

  • 有没有比传递分隔字符串并稍后解析它更优雅的方法来传递可选的整数列表到?我也有一个位置论点。 不工作,因为试图获取并抱怨它不是整数。 理想情况下,我想与其中一个执行 或者类似的东西,但也能