我有一个 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。但他们也可以使用特性 Animal 定义自己的动物,然后将其传递给函数 make_three_sounds。
现在,假设我希望从 Python 中使用这个库。所以我可以使用 PyO3 来制作 Rust -> Python 绑定。然而,问题是在 Python 中,这会以不同的方式实现。您将拥有一个可以扩展的类,而不是 trait。所以在 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 和 Cat 类,我只需要在 Dog 和 Cat 结构体上方使用“#[pyclass]”和“#[pymethods]”。问题在于创建一个可以扩展的 Animal 类,然后传递给函数 make_three_sounds。为了创建 Animal 类,我可以创建一个使用 Animal 特征的结构,然后在其上方添加“#[pyclass]”。
但问题是:当 Python 库的用户扩展该类(Animal)然后将其传递给 make_three_sounds 时,它将无法工作,因为 make_three_sounds 必须接受一个实现 trait Animal 的结构,而 Python 对象没有实现它特征(尽管它是扩展实现它的类/结构的类的对象)。我可以制作一个make_three_sounds
接受 PyAny 对象的函数包装器,但是我以后如何将该对象传递给实际make_three_sounds
函数?