Python binding to a function taking vec<struct> argument

Probably I miss something obvious here, because according to the internet the following should compile:

#[pyclass]
struct P2d {
    x: f64,
    y: f64
}

#[pyfunction]
pub fn try_vec_args(points: Vec<&P2d>) {
}

But it's not, the error is:

error[E0277]: the trait bound `Vec<&P2d>: FromPyObject<'_>` is not satisfied
  --> src/lib.rs:24:29
   |
24 | pub fn try_vec_args(points: Vec<&P2d>) {
   |                             ^^^ the trait `FromPyObject<'_>` is not implemented for `Vec<&P2d>`
   |
   = help: the trait `FromPyObject<'a>` is implemented for `Vec<T>`
   = note: required because of the requirements on the impl of `PyFunctionArgument<'_, '_>` for `Vec<&P2d>`

Inspired by this SO post:

I've tried all combinations of "&", i.e. Vec<P2d>, Vec<&P2d>, &Vec<P2d>and &Vec<&P2d> and it never compiles for me. As far as I understand, ideally I'd like to pass &Vec<P2d> argument because I don't want to transfer the ownership. Am I right here?

When I look at the error message on my own computer, it looks to me like function argument types must implement FromPyObject. There are a ton of implementors, but unfortunately none for slices (&[T]) or &Vec<T>. You could get Vec<P2d> to work when P2d implements Clone, according to this implementation of FromPyObject. I guess the easiest way though would be to define a PyClass wrapper type around Vec<P2d> and pass a reference to that to try_vec_args:

#![allow(dead_code)]

use pyo3::{pyclass, pyfunction};

#[pyclass]
pub struct P2d {
    x: f64,
    y: f64,
}

#[pyclass]
pub struct P2dVec(Vec<P2d>);

#[pyfunction]
pub fn try_vec_args(_points: &P2dVec) {}

This was actually the point I missed:

You could get Vec<P2d> to work when P2d implements Clone, according to this implementation of FromPyObject.

I derived my struct from Clone and now it compiles, thanks!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.