python - 返回对 PyO3 中成员字段的引用

标签 python rust pyo3

假设我有一个像这样的 Rust 结构

struct X{...}

struct Y{
   x:X
}
我希望能够编写访问 X 的 python 代码通过 Y
y = Y()
y.x.some_method()
在 PyO3 中实现它的最佳方法是什么?目前我做了两个包装类
#[pyclass]
struct XWrapper{
   x:X
}
#[pyclass]
struct YWrapper{
   y:Y
}
#[pymethods]
impl YWrapper{
   #[getter]
   pub fn x(&self)->XWrapper{
      XWrapper{x:self.y.clone()}
   }
}
但是,这需要 clone() .我宁愿要返回引用。我当然知道如果Xpyclass ,然后我可以轻松返回 PyRef到它。但问题是XY来自 Rust 库,我不能随意添加 #[pyclass]给他们。

最佳答案

如果不重新调整界面,我认为您所说的不可能:
您的 XWrapper拥有 x和您的 Y拥有其 x以及。这意味着创建一个 XWrapper将始终涉及克隆(或 new)。
可以换吗XWrapper以便它只包含对 x 的引用?不是真的,因为那需要给 XWrapper生命周期注释,而 PyO3 afaik 不允许带有生命周期注释的 pyclasses。有道理,因为将对象传递给 python 会将它放在 python 堆上,此时 rust 失去对对象的控制。
所以,我们能做些什么?
一些想法:你真的需要暴露y的组成结构吗?到python模块?仅仅因为它在 Rust 中的组织方式并不意味着它需要在 Python 中如此。您的 YWrapper可以为python接口(interface)提供方法,在后台将请求转发到x实例:

#[pymethods]
impl YWrapper{
   pub fn some_method(&self) {
     self.y.x.some_method();
   }
}
对于严格遵守迪米特法则的人来说,这也是一个受欢迎的景象;)
我在想其他聪明的方法。取决于一些细节如何y.x通过y的方法访问和修改本身,可能可以添加一个字段 x: XWrapperYWrapper .然后你创建 XWrapper (包括 y.x 的克隆)一次当 YWrapper已创建,然后您可以返回对该 XWrapper 的引用。在您的 pub fn x .当然,当 x 时,这会变得更加麻烦。通过 y 的方法频繁更改和更新...
在某种程度上,这证明了 Python 的引用计数对象模型和 Rust 的所有权对象模型之间的冲突。 Rust 强制你不能随意弄乱对象,除非你是它们的所有者。

关于python - 返回对 PyO3 中成员字段的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69665304/

相关文章:

memory - Rust取消提交并将内存返回给操作系统的策略是什么?

python - 如何使用 PyO3 解码 PyCodeObject?

rust - PyO3 - 从 PyObject 派生枚举

python - Django 'bool' 对象没有属性 '_committed'

python - 如何连接 Qt Designer 创建的单独的 UI 文件?

python - 下载可执行文件时有时权限被拒绝

rust - 如何使用与 C 打开函数匹配的 i32 提供的标志打开文件?

struct - 将结构从一个进程发送到另一个进程的最简单方法是什么?

python - Gensim Doc2Vec 按文档作者访问向量

rust - 怎么把PyObjectRef转换成PyString?