在 Rust 各个模块文件中使用宏程序
Nilesh Katuwal
2023年1月30日
在本文中,我们将学习如何在 Rust 中跨模块文件使用宏。
Rust 宏
Rust 提供了很好的宏支持。例如,通过宏启用的元编程涉及编写编写其他代码的代码。
宏
提供与函数相当的能力,但没有相关的运行时成本。由于宏
在编译时扩展,因此构建时间成本是相关的。
Rust 宏与 C 宏有很大不同。例如,Rust 宏应用于标记树,而 C 宏替换文本。
语法:
*MacroRulesDefinition* :
`macro_rules` `!` [IDENTIFIER] *MacroRulesDef*
MacroRules :
MacroRule ( ; MacroRule )* ;?
MacroRule :
MacroMatcher => MacroTranscriber
Rust 中跨箱子的宏
crate
包括模块范围的层次结构。crate 中的任何对象都有一个规范的模块路径,指示其在模块树中的位置。
在这个树的顶层,有一个匿名模块。Rust 源文件指定了一个模块,其名称和在当前 crate 的模块树中的位置是外部定义的:或者通过引用源文件中的显式 Module
项。
它也可能是板条箱本身的名称。每个源文件都是一个模块。
然而,并不是每个模块都需要它的源文件:模块定义可以在单个源文件中分层。
板条箱 util
:
#[macro_export]
macro_rules! foo {
() => ()
}
板条箱用户
:
use util::foo;
foo!();
请注意,使用此策略时,宏始终位于 crate 的顶层。即使 foo
包含在 mod bar
中,user
crate 仍然必须写 use util::foo;
而不是使用 util::bar::foo;
。
你可以使用 pub use
从 crate 的模块中导出宏。
Rust 中同一个 Crate 中的宏
foo::bar!();
mod foo {
macro_rules! bar {
() => ()
}
pub(crate) use bar;
}
foo::bar!();
宏可以通过 pub use
导入并用作任何其他对象。与旧方法不同,这不依赖于源代码顺序,因此你可以在宏编写之前使用它。
每个宏
都有一个名称和一个或多个规则
。每个规则由两部分组成:一个匹配器,它描述它匹配的语法,一个转录器,它描述将被成功匹配的调用替换的语法。
分隔符必须包含匹配器和转录器。表达式、语句、特征、实现、外来项、类型和模式可以通过宏进行扩展。