簡體   English   中英

PyO3 - 傳遞類擴展另一個類作為函數參數

[英]PyO3 - passing class extending another class as a function argument

我有一個 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]”。 問題在於創建一個可以擴展然后傳遞給函數 make_three_sounds 的 Animal 類。 為了創建 Animal 類,我可以創建一個將使用 Animal trait 的結構,然后在其上方添加“#[pyclass]”。

但問題是:當 Python 庫的用戶擴展該類 (Animal) 然后將其傳遞給 make_three_sounds 時,它將不起作用,因為 make_three_sounds 必須接受一個實現 trait Animal 的結構,而該 Python 對象沒有實現那個trait(雖然它是一個類的對象,它擴展了一個實現它的類/結構)。 我可以制作接受 PyAny 對象的make_three_sounds函數的包裝器,但是稍后我將如何將該對象傳遞給實際的make_three_sounds函數?

我可以看到的一種解決方案如下。

我創建了一個函數make_three_sounds(PyAny a) ,它將是 Rust make_three_sounds(&impl Animal a)函數的包裝器。 該包裝器將接受 PyAny 類型的對象。 稍后我將執行以下操作。 我將有一個特殊的結構 PyAnimal 實現 trait Animal。 該特征將有一個名為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');
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM