微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PyO3-传递类,将另一个类扩展为函数参数

如何解决PyO3-传递类,将另一个类扩展为函数参数

我在Rust中有一个库,我希望能够从Python使用它。所以我可以使用PyO3进行绑定。

让我们假设我在Rust中有一个以下库:

pub trait Animal {
    fn make_sound();
}

pub struct Dog {}

impl Animal for Dog {
    fn make_sound() {
       println!("whoof whoof");
    }
}

pub struct Cat {}

impl Animal for Cat {
    fn make_sound() {
       println!("miaauwwww");
    }
}

pub fn make_three_sounds(&impl Animal) {
    animal.make_sound();
    animal.make_sound();
    animal.make_sound();
}

该库的用户可以使用Dog和Cat结构以及make_three_sounds函数。但是他们也可以使用动物特性来定义自己的动物,然后将其传递给函数make_three_sounds。

现在,让我们说我想从Python使用此库。因此,我可以使用PyO3制作Rust-> Python绑定。但是,问题在于在Python中这将以不同的方式实现。除了特质,您将拥有一个可以扩展的类。因此在Python中,该库如下所示:

Class Animal:
    def make_sound():
        raise Error("Unimplemented abstract method")

class Dog(Animal):
    def make_sound():
        print("woaggh woafgg")

class Cat(Animal):
    def make_sound():
        print("miaaoww")

def make_three_sounds(a: Animal):
    a.make_sound()
    a.make_sound()
    a.make_sound()

为了制作Dog and Cat类,我只需要在Dog and Cat结构上面使用“#[pyclass]”和“#[pymethods]”。问题在于制作一个可以扩展的Animal类,然后将其传递给函数make_three_sounds。为了制作Animal类,我可以创建一个使用Animal特性的结构,然后在其上添加“#[pyclass]”。

但是问题是:当Python库的用户扩展该类(Animal),然后将其传递给make_three_sounds时,它将不起作用,因为make_three_sounds必须接受实现特征Animal的结构,而该Python对象却不能。实现该特征(尽管它是扩展实现该特征的类/结构的类的对象)。我可以对接受PyAny对象的make_three_sounds函数进行包装,但是以后如何将该对象传递给实际的make_three_sounds函数呢?

解决方法

我可以看到的一种解决方案如下。

我创建了一个函数make_three_sounds(PyAny a),它将成为Rust make_three_sounds(&impl Animal a)函数的包装器。该包装器将接受PyAny类型的对象。稍后,我将执行以下操作。我将有一个实现Animal的特殊结构PyAnimal。该特征将具有一个名为python_object的属性。来自Python的PyAny对象(代表扩展Animal的类的对象)将稍后分配给该属性python_object。 PyAnimal将必须实现trait方法,并且该方法的实现将在python_object上调用该方法(PyAny结构具有可调用该对象的任何方法的callmethod方法)。然后,该PyAnimal对象将传递给make_three_sounds(&impl Animal a)函数。因此,PyAnimal的实现将或多或少如下:

struct PyAnimal {
    python_object: PyAny
}

impl Animal for PyAnimal {
   fn make_sound() {
       python_object.call_method('make_sound');
   }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。