英文:
How to modify Python list of custom rust objects from within Rust with PyO3?
问题
抱歉,您的代码示例中包含HTML转义字符,我将为您提供未经转义的代码,以便更好地理解问题:
use pyo3::prelude::*;
#[pyclass]
pub struct ListElement {
pub value_sum: f32
}
#[pymethods]
impl ListElement {
#[new]
fn new(value_sum: f32) -> Self {
ListElement { value_sum }
}
fn add_value(&mut self, value: f32) {
self.value_sum += value;
}
}
#[pyfunction]
fn modify_list_elements(list: Vec<&ListElement>, value: f32){
for mut elem in list {
elem.add_value(value);
}
}
#[pymodule]
fn my_rust_module(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<ListElement>()?;
m.add_function(wrap_pyfunction!(modify_list_elements, m)?)?;
Ok(())
}
Cargo.toml
文件也应该是未经HTML转义的。至于您遇到的错误,请确保您的 modify_list_elements
函数接受 Vec<&ListElement>
,而不是 Vec<&ListElement>
。将代码中的 <
和 &
更改为正常的 <
和 &
,并重新构建项目,应该能够解决这个问题。
希望这可以帮助您解决问题!如果您有其他问题,请随时提问。
英文:
I'm new to Rust and I have a problem. I have list in Python. It is a list of objects implemented in PyO3 Rust. I want to pass it to a function to make some changes to the elements.
This is minimal reproducible example:
use pyo3::prelude::*;
#[pyclass]
pub struct ListElement {
pub value_sum: f32
}
#[pymethods]
impl ListElement {
#[new]
fn new(value_sum: f32) -> Self {
ListElement { value_sum }
}
fn add_value(&mut self, value: f32) {
self.value_sum += value;
}
}
#[pyfunction]
fn modify_list_elements(list: Vec<&ListElement>, value: f32){
for mut elem in list {
elem.add_value(value);
}
}
#[pymodule]
fn my_rust_module(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<ListElement>()?;
m.add_function(wrap_pyfunction!(modify_list_elements, m)?)?;
Ok(())
}
this is my Cargo.toml
[package]
name = "my_rust_module"
version = "0.1.0"
edition = "2018"
[lib]
# The name of the native library. This is the name which will be used in Python to import the
# library (i.e. `import string_sum`). If you change this, you must also change the name of the
# `#[pymodule]` in `src/lib.rs`.
name = "my_rust_module"
# "cdylib" is necessary to produce a shared library for Python to import from.
#
# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
# to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
# crate-type = ["cdylib", "rlib"]
crate-type = ["cdylib"]
[dependencies]
pyo3 = { version = "0.19.0", features = ["extension-module"] }
This is error that I get when I use
maturin develop
🔗 Found pyo3 bindings
🐍 Found CPython 3.7 at C:\my_paths\python.exe
📡 Using build options features from pyproject.toml
Compiling my_rust_module v0.1.0 (C:\my_paths\my_rust_module)
error[E0277]: the trait bound `Vec<&ListElement>: FromPyObject<'_>` is not satisfied
--> src\lib.rs:22:31
|
22 | fn modify_list_elements(list: Vec<&ListElement>, value: f32){
| ^^^ the trait `FromPyObject<'_>` is not implemented for `Vec<&ListElement>`
|
= help: the trait `FromPyObject<'a>` is implemented for `Vec<T>`
= note: required for `Vec<&ListElement>` to implement `PyFunctionArgument<'_, '_>`
note: required by a bound in `extract_argument`
--> C:\my_paths\.cargo\registry\src\index.crates.io-6f17d22bba15001f\pyo3-0.19.0\src\impl_\extract_argument.rs:86:8
|
86 | T: PyFunctionArgument<'a, 'py>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`
For more information about this error, try `rustc --explain E0277`.
I tried to google it, understand output of rustc --explain E0277, but I still dont know how to do it.
Any help would be appreciated.
答案1
得分: 1
问题在于 Vec<T>
只有在 T
也实现了 FromPyObject
时才能实现,但 &ListElement
并不实现该特性。
你可以通过以下两种方法之一来修复它:
-
派生它:
#[pyclass] #[derive(FromPyObject)] pub struct ListElement { pub value_sum: f32 }
-
改用
Vec<PyRefMut<ListElement>>
,它会自动实现FromPyObject
特性:#[pyfunction] fn modify_list_elements(list: Vec<PyRefMut<ListElement>>, value: f32){ for mut elem in list { elem.add_value(value); } }
英文:
The problem here is that Vec<T>
only implements FromPyObject
if T
also does so, but &ListElement
doesn't implement that trait.
You can fix it in one of two ways:
- Derive it:
#[pyclass] #[derive(FromPyObject)] pub struct ListElement { pub value_sum: f32 }
- Take
Vec<PyRefMut<ListElement>>
instead for whichFromPyObject
is automatically implemented by thepyclass
attribute:#[pyfunction] fn modify_list_elements(list: Vec<PyRefMut<ListElement>>, value: f32){ for mut elem in list { elem.add_value(value); } }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论