python - 编写一个等效于 Python 函数的 pyo3 函数,该函数返回其输入对象
问题描述
我正在为我的库编写一个 Rust 后端,我需要在以下函数中实现等价的功能pyo3
:
def f(x):
return x
这应该返回与输入相同的对象,并且获取返回值的函数应该持有对输入的新引用。如果我在 C API 中写这个,我会写成:
PyObject * f(PyObject * x) {
Py_XINCREF(x);
return x;
}
在PyO3PyObject
中,我发现导航, PyObjectRef
, &PyObject
, Py<PyObject>
,之间的差异非常令人困惑Py<&PyObject>
。
这个函数最幼稚的版本是:
extern crate pyo3;
use pyo3::prelude::*;
#[pyfunction]
pub fn f(_py: Python, x: &PyObject) -> PyResult<&PyObject> {
Ok(x)
}
除其他外,的生命周期x
和返回值不一样,加上我看不到pyo3
增加引用计数的机会x
,事实上编译器似乎同意我的观点:
error[E0106]: missing lifetime specifier
--> src/lib.rs:4:49
|
4 | pub fn f(_py: Python, x: &PyObject) -> PyResult<&PyObject> {
| ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_py` or `x`
我可能有一种方法可以使用参数手动增加引用计数_py
并使用生命周期注释来使编译器满意,但我的印象是pyo3
打算使用对象生命周期来管理引用计数本身。
编写此函数的正确方法是什么?我应该尝试将其包装在Py
容器中吗?
解决方案
APyObject
是原始指针的简单包装器:
pub struct PyObject(*mut ffi::PyObject);
它有多个创建函数,每个函数对应于我们可能从 Python 获得的不同类型的指针。其中一些,例如from_borrowed_ptr
,调用Py_INCREF
传入的指针。
因此,我们似乎可以接受 a PyObject
,只要它是以“正确”的方式创建的。
如果我们展开这段代码:
#[pyfunction]
pub fn example(_py: Python, x: PyObject) -> PyObject {
x
}
我们可以看到调用我们函数的这段代码:
let mut _iter = _output.iter();
::pyo3::ObjectProtocol::extract(_iter.next().unwrap().unwrap()).and_then(
|arg1| {
::pyo3::ReturnTypeIntoPyResult::return_type_into_py_result(example(
_py, arg1,
))
},
)
我们的论点是由对 的调用创建的ObjectProtocol::extract
,而后者又调用FromPyObject::extract
. 这是通过调用来实现的PyObject
from_borrowed_ptr
。
因此,使用 barePyObject
作为参数类型将正确地增加引用计数。
同样,当PyObject
在 Rust 中删除 a 时,它会自动减少引用计数。当它返回给 Python 时,所有权被转移,由 Python 代码来适当地更新引用计数。
从主分支对提交 ed273982进行的所有调查,对应于 v0.5.0-alpha.1。
推荐阅读
- google-sheets - 基于总和的谷歌表格中的数据验证
- python - python运行多个脚本
- python - 有没有办法使用 selenium 或其他方式与 Discord 屏幕共享权限弹出窗口交互
- json - 如何使用 jmeter 从 json 断言中识别特定的真或假值?
- sql - 如果必须分块处理数据,从sql将数据加载到redis中会更好吗?
- android - 在 Android 10 或更高版本中从后台服务启动 Activity
- c++ - 如何使用 C++ 覆盖二进制文件的一部分?
- awk - 使用列数据打印列的 awk 命令
- google-chrome - Chromium 源代码树中的“站点设置”在哪里?
- javascript - 如何在 ReactJS 中使用事件监听器?