Skip to content

过程宏

语法树解析网站:

https://astexplorer.net/

过程宏接收 Rust 代码作为输入,在这些代码上进行操作,然后产生另一些代码作为输出,而非像声明式宏那样匹配对应模式然后以另一部分代码替换当前代码。

有三种类型的过程宏(自定义派生(derive),类属性和类函数),不过它们的工作方式都类似。

当创建过程宏时,其定义必须位于一种特殊类型的属于它们自己的 crate 中

使用这些宏需采用类似示例 19-29 所示的代码形式,其中 some_attribute 是一个使用特定宏的占位符。

示例 19-29: 一个使用过程宏的例子

src/lib.rs:

1
2
3
4
5
use proc_macro;

#[some_attribute]
pub fn some_name(input: TokenStream) -> TokenStream {
}

过程宏包含一个函数,这也是其得名的原因:“过程” 是 “函数” 的同义词。
那么为何不叫 “函数宏” 呢?好吧,有一个过程宏是 “类函数” 的,叫成函数会产生混乱。
无论如何,定义过程宏的函数接受一个 TokenStream 作为输入并产生一个 TokenStream 作为输出。
这也就是宏的核心:宏所处理的源代码组成了输入 TokenStream,同时宏生成的代码是输出 TokenStream。最后,函数上有一个属性;这个属性表明过程宏的类型。
在同一 crate 中可以有多种的过程宏。

考虑到这些宏是如此类似,我们会从自定义派生宏开始。接着会解释与其他形式宏的微小区别。

如何编写自定义 derive 宏

1
cargo new --lib hello_macro