0

我创建了一个 Rust 库,用于从 Python 中进行一些繁重的处理。它工作得相当好,但我留下的代码感觉臃肿且难以维护,所以我认为必须有更好的方法。我使用各种特征和枚举尝试了一些不同的选项,但很难做出任何真正的改进。我没有做过那么多 Rust,所以我猜测(并希望)我错过了一个好的、干净的解决方案。

rust 包基本上只是一个单一的核心结构,包含一些数据和相当多的实现方法。然后,它被一个 pyclass 结构包装以处理 Python 的接口。核心结构需要是通用的,或者至少最终的 python 类需要能够处理几种不同的数据类型。更复杂的是,我在其他 Rust 项目中使用了核心结构,所以我想将任何与 python 相关的东西排除在核心结构之外。

我最终使用了一系列巨大的宏来创建一些接口结构,一个来处理每种不同的数据类型。我发现这些宏很难使用,但我还没有想出简化或删除它们的方法。因此,如果有人对从这里去哪里有任何想法或提示,那将非常感激。

这是我的代码的一个极其简化的版本:

// main.rs
use pyo3::prelude::*;

pub mod core;
pub mod interface;

use interface::{FloatClass, IntClass, StrClass};

#[pymodule]
fn pyo3_test(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<FloatClass>()?;
    m.add_class::<IntClass>()?;
    m.add_class::<StrClass>()?;
    Ok(())
}
// core.rs
pub struct Core<T> {
    pub data: Vec<T>,
}

impl<T> Core<T> {
    pub fn a(&self) {
        println!("running: a");
    }
    pub fn b(&self) {
        println!("running: b");
    }
    // lots more methods...
    pub fn z(&self) {
        println!("running: z");
    }
}
// interface.rs
use pyo3::prelude::*;

use crate::core::Core;

macro_rules! create_interface {
    ($name: ident, $type: ident) => {
        #[pyclass]
        pub struct $name {
            pub inner: Core<$type>,
        }
        #[pymethods]
        impl $name {
            #[new]
            pub fn from_vector(data: Vec<$type>) -> Self {
                Self { inner: Core { data: data } }
            }
            pub fn a(&self) {
                self.inner.a()
            }
            pub fn b(&self) {
                self.inner.b()
            }
            // need to implement each method here as well
            // often using conversions to/from python types
            pub fn z(&self) {
                self.inner.z()
            }
        }
    };
}

create_interface!(IntClass, i64);
create_interface!(FloatClass, f64);
create_interface!(StrClass, String);

接口中实现的方法显然远比本例中的复杂和独特,因此泛化接口方法会很困难。

感谢您的任何想法。

4

0 回答 0