【问题标题】:Vector of custom struct in PyO3PyO3 中自定义结构的向量
【发布时间】:2019-06-10 07:49:27
【问题描述】:

我是 Rust 和 PyO3(来自 Python)的新手,所以这对更有经验的人来说可能很明显。

我在 PyO3 中声明了一个 pyclass 结构。

#[pyclass]
struct Block {
    start: i32,
    stop: i32,
}

然后我在 rust 函数中使用 Block,该函数接受 Block 的向量并输出 int 的向量(签名如下)

#[pyfunction]
fn from_blocks(block_list: Vec<Block>) -> Vec<i32>

当我使用nightly-x86_64-apple-darwin 编译时,我收到以下错误:

#[pyfunction]
^^^^^^^^^^^^^ the trait `pyo3::FromPyObject<'_>` is not implemented for `std::vec::Vec<Block>`

我该如何解决这个问题?

编辑: 曹是对的。我在追溯错误时犯了一个错误。 之前写过

然后我在一个 rust 函数中使用 Block,该函数接受一个 int 向量并输出一个 Block 向量(签名如下)

#[pyfunction]
fn to_blocks(list: Vec<i32>) -> Vec<Block>

但实际的冒犯功能是:

#[pyfunction]
fn from_blocks(block_list: Vec<Block>) -> Vec<i32>

我已更新问题以使其更清楚。

【问题讨论】:

  • 抱歉给大家带来了困惑。 @Caio 直观地发现违规函数具有反向签名。结果我更新了这个问题。

标签: python rust pyo3


【解决方案1】:

看起来pyfunction 属性生成的代码要求返回类型实现FromPyObject 特征。虽然有 FromPyObject for Vec&lt;T&gt; where T: FromPyObject 的一揽子实现,但看起来为 pyclass 属性生成的代码不包括您的 Block 类型的 FromPyObject 实现。

由于我对 PyO3 不熟悉,除了几分钟我只是查看了它的 API 文档来验证这个答案,我不确定如何最好地获得 FromPyObject 实现——也许有一个 derive为了它?

【讨论】:

    【解决方案2】:

    FromPyObject 旨在供可以从 Python 世界中提取的类型使用。这就是为什么我认为您试图写fn to_blocks(list: Vec&lt;Block&gt;) -&gt; Vec&lt;i32&gt; 而不是fn to_blocks(list: Vec&lt;i32&gt;) -&gt; Vec&lt;Block&gt;。如果是这样的话,让我们进入实现链。

    FromPyObject 具有any &T that implements PyTryFrom 的默认实现,PyTryFrom 具有any T that implements PyTypeInfo 的默认实现。 [pyclass] 根据impl_class 方法实现PyObjectAllocPyObjectWithFreeList,并且两个特征都具有PyTypeInfo 特征绑定。因此,您的类/结构将与引用一起正常工作,例如:

    #[pyfunction]
    fn to_blocks(list: Vec<&Block>) -> Vec<i32>
    

    你可以在官方文档中看到这个解释的总结。

    FromPyObject由各种可以提取的类型实现 来自 Python 对象reference

    【讨论】:

    • 为什么一个名为to_blocks 的函数会将一个块向量作为输入并返回一个整数向量?
    • 尽管有这个名字,fn to_blocks(list: Vec&lt;i32&gt;) -&gt; Vec&lt;Block&gt; 编译没有问题,即使它没有编译,错误也会有所不同。
    • 我不明白你的评论。如果它编译没有问题,那么为什么要修复它?在任何情况下,建议交换函数的输入和输出是没有意义的,因为这不会为 OP 提供他们需要的东西。
    • 他在这个问题中给出的编译错误仅与自定义派生不足以使本地拥有的类型在函数参数中使用这一事实有关。这就是为什么我建议可能编写了错误的代码,并且如果是这种情况,则需要对这个答案采取上述措施.如果我不够清楚,我可以以适当的方式编辑我的帖子。
    • @interjay,@caio 为混乱道歉。我认为@caio 发现我因为我有一个 fn to_blocks 然后有一个相反的反面,这就是导致错误的原因。
    【解决方案3】:

    您使用的是哪个版本的 PyO3? 您的代码在 0.5.30.6.0-alpha.1 上为我工作。

    因此我无法对此进行测试,但我猜你需要返回一个PyResult

    #[pyfunction]
    fn to_blocks(list: Vec<i32>) -> PyResult<Vec<Block>>
    

    【讨论】:

    • #[pyclass]Block 实现了IntoPyObject/ToPyObject,这就是它起作用的原因。操作码应该是fn to_blocks(list: Vec&lt;Block&gt;) -&gt; Vec&lt;i32&gt;
    • @Caio 我很困惑——既然 OP 的代码有效,为什么它应该是别的东西?
    • 因为他给出的错误信息与将Block 用作输入参数时得到的错误信息相同。可以肯定的是,我认为最好等待他对此事的回应。
    • @Caio 你是对的,我将错误追溯到错误的函数。错误源于fn from_blocks(block_list: Vec&lt;Block&gt;) -&gt; Vec&lt;i32&gt;
    • @kentwait 谢谢=)
    猜你喜欢
    • 2022-11-15
    • 2017-11-23
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多