SOLVED: Pyo3 class method to accept generic

I maintain the python 3D graphics module pi3d and I'm looking at making a rust version accessible from python. 18 months ago I started experimenting with a rust version github.com/paddywwoof/rust_pi3d and now I'm attempting to wrap it using pyo3. Mainly this all seems to work quite well, but my issue is how to have a class method add_child() on Cuboid, Sphere, Cone etc. etc (which are all just wrappers with different constructors for Shape) that can accept Cuboid, Sphere, Cone types.

When I try a pyo3 version of the code below I get the error A Python method can't have a generic add_child parameter: type. I suspect the solution might something to do with pyo3 PyObjects but I haven't been able to find anything in docs.

#[derive(Clone, Debug)]
struct Shape {
    a: i32,
    children: Vec<Shape>,
}

trait GetShape {
    fn get_shape(&mut self) -> Shape;
}

#[derive(Debug)]
struct Cuboid {
    shape: Shape,
}
impl GetShape for Cuboid {
    fn get_shape(&mut self) -> Shape {
        self.shape.clone()
    }
}
impl Cuboid {
    fn add_child<T: GetShape>(&mut self, other: &mut T) {
        self.shape.children.push(other.get_shape());
    }
}

#[derive(Debug)]
struct Sphere {
    shape: Shape,
}
impl GetShape for Sphere {
    fn get_shape(&mut self) -> Shape {
        self.shape.clone()
    }
}
impl Sphere {
    fn add_child<T: GetShape>(&mut self, other: &mut T) {
        self.shape.children.push(other.get_shape());
    }
}

fn main() {
    let mut cube = Cuboid {
            shape: Shape {a:33, children: vec![]},
        };
    let mut sphere = Sphere {
            shape: Shape {a:366, children: vec![]},
        };
    cube.add_child(&mut sphere);
    println!("{:?}", cube);
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c4f77615a087a75e11752b22bdf68c06

It's possible to do something like this using (extends=..) as explained here: https://github.com/PyO3/pyo3/issues/696

grateful thanks to @kngwyu on the pyo3 github repo

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.