简体   繁体   中英

Vector of custom struct in PyO3

I'm new to Rust and PyO3 (coming from Python) so this might be obvious to more experienced people.

I declared a pyclass struct in PyO3.

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

Then I use Block in a rust function that takes a vector of Block and outputs a vector of int (signature below)

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

When I compile using nightly-x86_64-apple-darwin I get the following error:

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

How do I solve this?

EDIT: Caio is right. I made a mistake in tracing back the error. Previously I wrote

Then I use Block in a rust function that takes a vector of int and outputs a vector of Block (signature below)

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

But the actual offending function is:

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

I've updated the question to make it clearer.

FromPyObject is intended to be used by types that can be extracted from the Python world. That is why I think that you were trying to write fn to_blocks(list: Vec<Block>) -> Vec<i32> instead of fn to_blocks(list: Vec<i32>) -> Vec<Block> . If that is the case , lets go down to the implementation chain.

FromPyObject has a default implementation for any &T that implements PyTryFrom and PyTryFrom has a default implementation for any T that implements PyTypeInfo . [pyclass] implements PyObjectAlloc or PyObjectWithFreeList according to the impl_class method and both traits have the PyTypeInfo trait bound. Therefore, your class/struct will work just fine with references, eg:

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

You can see in the official documentation this explanation in a summarized way.

FromPyObject is implemented by various types that can be extracted from a Python object reference .

It looks like the pyfunction attribute generates code that requires that the return type implements the FromPyObject trait. While there's a blanket implementation of FromPyObject for Vec<T> where T: FromPyObject , it looks like the code generated for pyclass attribute does not include an implementation of FromPyObject for your Block type.

Since I am unfamiliar with PyO3 other than the few minutes I just looked at its API documentation to validate this answer, I'm not sure how you'd best get a FromPyObject implementation -- perhaps there's a derive for it?

Which version of PyO3 are you on? Your code is working for me on 0.5.3 and 0.6.0-alpha.1 .

Due to that I can't test this, but I would guess that you need to return a PyResult :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM