Как сгенерировать макрос из предыдущего кода, сгенерированного макросом?

Чтобы создать класс Python на основе pyo3, работающий со структурой, использующей универсальный тип, я хочу использовать оболочки, которые будут генерировать код, необходимый для того, чтобы не делать это для каждого конкретного типа.

Я создал макрос, который генерирует код, но мне нужно зарегистрировать функции, сгенерированные моим макросом, как функции модуля Python.

Один из способов - отслеживать идентификаторы, используемые в макросе, чтобы использовать их и генерировать wrap_pyfunction с другим макросом, но я не могу найти ничего связанного.

(Конечно, любое другое решение для генерации кода будет тепло встречено)

(Упрощенный) код, который у меня есть прямо сейчас:

      macro_rules! create_python_function {
    ($name:ident, $objtype:expr) => {
        paste!{
            #[pyclass(unsendable)]
            pub struct [<$name PyIface>] {
                obj: GenericStruct<$objtype>,
            }

            impl [<$name PyIface>]{
                pub fn new() -> [<$name PyIface>]{
                    [<$name PyIface>] {}
                }
            }

            pub fn [<create_object_ $name>]() -> [<$name PyIface>]{
                [<$name PyIface>]::new()
            }
        }
    };
}

create_python_function!(name, SpecificType);

#[pymodule]
fn mymodule(_py: Python, m: &PyModule) -> PyResult<()> {
    /* I want to auto-generate this with macro
     * m.add_function(wrap_pyfunction!(create_object_name, m)?).unwrap(); 
     */
    Ok(())
}

1 ответ

Макросы не могут делиться своими аргументами или состояниями. Если вы не хотите повторять идентификаторы, переместите mymodule определение в create_python_functionмакрос и измените макрос, чтобы использовать повторения (Справочник по Rust)

      macro_rules! create_python_function {
    ($($name:ident => $objtype:ty),* $(,)?) => {
        $(
            paste! {
                #[pyclass(unsendable)]
                pub struct [<$name PyIface>] {
                    obj: GenericStruct<$objtype>,
                }

                impl [<$name PyIface>]{
                    pub fn new() -> [<$name PyIface>]{
                        [<$name PyIface>] { obj: todo!() }
                    }
                }

                pub fn [<create_object_ $name>]() -> [<$name PyIface>]{
                    [<$name PyIface>]::new()
                }
            }
        )*

        #[pymodule]
        fn mymodule(_py: Python, m: &PyModule) -> Result<(), ()> {
            $(
                paste! {
                    m.add_function(wrap_pyfunction!([<create_object_ $name>], m)?).unwrap();
                }
            )*
            Ok(())
        }
    };
}

struct Foo;
create_python_function!(
    foo => Foo,
    v => Vec<()>,
);
Другие вопросы по тегам