【问题标题】:PyO3 convert rust struct to &PyAnyPyO3 将 rust 结构转换为 &PyAny
【发布时间】:2021-06-21 12:45:34
【问题描述】:

我有一个结构

#[pyclass]
pub struct DynMat {
   ...
}

我有这个功能

#[pyfunction]
#[text_signature = "(tensor/)"]
pub fn exp<'py>(py: Python<'py>, tensor_or_scalar: &'py PyAny) -> PyResult<&'py PyAny> {
    // I need to return &PyAny because I might either return PyFloat or DynMat
    if let Ok(scalar) = tensor_or_scalar.cast_as::<PyFloat>() {
        let scalar: &PyAny = PyFloat::new(py, scalar.extract::<f64>()?.exp());
        Ok(scalar)
    } else if let Ok(tensor) = tensor_or_scalar.cast_as::<PyCell<DynMat>>() {
        let mut tensor:PyRef<DynMat> = tensor.try_borrow()?;
        let tensor:DynMat = tensor.exp()?;
        // what now? How to return tensor
    }
}

问题是,我怎样才能从一个期望 PyResult&lt;&amp;'py PyAny&gt; 的函数返回一个标有 pyclass 的 Rust 结构

【问题讨论】:

    标签: python rust pyo3


    【解决方案1】:

    我假设您要返回的是 tensor

    如果您的返回类型是 PyResult&lt;DynMat&gt;,您可以直接返回它并让自动转换开始。但我假设根据您是标量还是张量,您将返回不同的类型。

    所以,现在您将tensor 作为DynMat 在一个拥有的值,我们需要将它移动到python 堆。看起来是这样的:

    let tensor_as_py = Py::new(py, tensor)?.into_ref(py);
    return Ok(tensor_as_py);
    
    

    PS:你也可以更简洁地写下你的转换尝试:

    pub fn blablabla() {
      let tensor: PyRefMut<DynMat> = tensor_or_scalar.extract();
      if let Ok(tensor) = tensor {
        let tensor = tensor.exp();
    

    但是看看你的代码,还有一件事让我很困惑:

    要对张量求幂,您是在可变地借用它。这向我表明,求幂将就位。那你为什么还要退货呢?

    或者这是否意味着对原始张量的引用?在这种情况下,我会去掉变量阴影,这样您就可以返回 PyRefMut&lt;DynMat&gt;,您可以通过 frominto 将其转换为 &amp;PyAny

    但实际上,tensor.exp()? 似乎返回了 DynMat 类型的拥有值,所以它似乎毕竟创建了一个 new 张量。在这种情况下,是的,您需要使用上面显示的Py::new 方法将其从 Rust 移动到 python 堆。

    编辑: 以前的版本使用 as_ref(py) 而不是 into_ref(py)。前者借用 Py&lt;_&gt; 对象给你一个参考,但后者实际上消耗 Py&lt;_&gt; 对象。

    文档实际上在这里准确地解释了您的用例https://docs.rs/pyo3/0.13.2/pyo3/prelude/struct.Py.html#method.into_ref

    【讨论】:

    • 借阅检查器有问题。如果我像你说的Py::new(py, tensor)?.as_ref(py) 那样引用,我会得到temporary value created herereturns a value referencing data owned by the current function。如何确保创建的引用使用生命周期 'py
    • 啊。我实际上并没有尝试编译并假设 IDE 会告诉我这个问题:D 简单的错字,请参阅我的编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 2015-09-08
    • 2022-01-05
    • 1970-01-01
    相关资源
    最近更新 更多