如何在宏中使用非公共函数?

Ren*_*ato 5 rust

我有一个变得太大的宏,所以我想将部分代码提取到一个函数中。当我这样做时,我遇到了问题,因为在调用站点扩展宏时该函数不在范围内:

#[macro_use]
mod macros {
    fn hi() {
        println!("Hello")
    }

    #[macro_export]
    macro_rules! say_hi {
        () => {
            hi();
        };
    }
}

fn main() {
    say_hi!();
}
Run Code Online (Sandbox Code Playgroud)

这不编译:

#[macro_use]
mod macros {
    fn hi() {
        println!("Hello")
    }

    #[macro_export]
    macro_rules! say_hi {
        () => {
            hi();
        };
    }
}

fn main() {
    say_hi!();
}
Run Code Online (Sandbox Code Playgroud)

我尝试hi公开(尽管我不想公开)但由于它不是在调用者的上下文中导入的,因此无论如何它都不起作用。

我怎么解决这个问题?

Ren*_*ato 6

第一个问题是,在宏调用者的上下文中,除非该函数是公共的,否则该函数不可见,因此恐怕无法从宏调用非 pub 函数。

另一个问题是宏引用的函数应始终使用其完全限定路径(以便它们在任何上下文中工作)。假设该功能hi已完成pub,这将起作用:

#[macro_export]
macro_rules! say_hi {
    () => {
        $crate::macros::hi();
    };
}
Run Code Online (Sandbox Code Playgroud)

注意:用于$crate确保宏在任何 crate 中使用时都有效,请参阅$crate 文档了解详细信息。

  • 常见的做法是在函数名称前加上一些指示符,表明它不是公共的(例如`__private_hi()`),然后将函数标记为`#[doc(hidden)]`,这样它就不会轻易出现。在宏中使用特殊的“$crate”变量也是一个很好的做法。 (3认同)
  • `$crate` 只给你箱子等级;您需要附加模块“路径”。即 `$crate::macros::hi()` (当然还有 `pub mod macro` 和 `pub fn hi`) (3认同)