I have a library in Rust and I want to be able to use it from Python. So I can do the bindings using PyO3.
Let's suppose that I have a following library in 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();
}
The user of that library can use the structs Dog and Cat and a function make_three_sounds. But they can also use the trait Animal to define their own animals and then pass it to the function make_three_sounds.
Now, let's say that I want this library to be used from Python. So I can use PyO3 to make the Rust -> Python bindings. However, the problem is that in Python this would be implemented differently. Instead of trait, you would have a class which you can extend. So in Python that library would look like this:
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()
In order to make a class Dog and Cat, I only need to use "#[pyclass]" and "#[pymethods]" above the Dog and Cat structs. The problem is with making an Animal class that you can extend and then pass to the function make_three_sounds. For making the Animal class, I can create a struct that will use Animal trait and then add "#[pyclass]" above that.
But the problem is: when the user of the Python library extends that class (Animal) and then pass it to make_three_sounds, then it won't work because make_three_sounds must accept a struct that implements trait Animal and that Python object doesn't implement that trait (although it's an object of a class that extends a class/struct that implements it). I can make a wrapper of make_three_sounds
function that accepts PyAny object, but how will I later pass that object to the actual make_three_sounds
function?