1

Pythonでの使用を許可するために、pyo3 pyclass マクロを使用する錆構造体があります。これは単純な構造体では問題なく機能しますが、別のライブラリの型を含む構造体があると、より困難になります。

例:

use geo::Point;

#[pyclass]
#[derive(Clone, Copy)]
pub struct CellState {
    pub id: u32,
    pub position: Point<f64>,
    pub population: u32,
}

上記では、rust geo ライブラリの Point タイプを使用しています。コンパイラは、次のエラーを提供します。 the trait `pyo3::PyClass` is not implemented for `geo::Point<f64>

Point に PyClass を実装しようとすると、次のようになります。

impl PyClass for Point<f64> {}

次のコンパイラ エラーが表示されます。 impl doesn't use only types from inside the current crate

これを解決するためのクリーンでシンプルな方法に関するアイデアはありますか?

4

1 に答える 1

0

より良い答えが出るまで、私の解決策はクラスをpythonクラス内にネストすることでしたが、その後、ゲッターとセッターを手動で作成する必要がありました。

#[pyclass]
#[derive(Clone)]
pub struct CellStatePy {
    pub inner: CellState,
}

#[pymethods]
impl CellStatePy {
    #[new]
    pub fn new(id: u32, pos: (f64, f64), population: u32) -> Self {
        CellStatePy {
            inner: CellState {
                id: CellIndex(id),
                position: point!(x: pos.0, y: pos.1),
                population,
            },
        }
    }
}

次に、PyObjectProtocol を実装します。

#[pyproto]
impl PyObjectProtocol for CellStatePy {
    fn __str__(&self) -> PyResult<&'static str> {
        Ok("CellStatePy")
    }

    fn __repr__<'a>(&'a self) -> PyResult<String> {
        Ok(format!("CellStateObj id: {:?}", self.inner.id))
    }

    fn __getattr__(&'a self, name: &str) -> PyResult<String> {
        let out: String = match name {
            "id" => self.inner.id.into(),
            "position" => format!("{},{}", self.inner.position.x(), self.inner.position.y()),
            "population" => format!("{}", self.inner.population),
            &_ => "INVALID FIELD".to_owned(),
        };
        Ok(out)
    }
}

于 2021-01-27T12:58:01.893 に答える