在Rust
中,属性宏(Attribute Macros)是一种强大的元编程工具。它们允许开发者通过自定义属性(以#[...]
的形式)来扩展Rust
语言的语法,从而在编译时对代码进行转换。属性宏在编译阶段起作用,能够读取和修改Rust
抽象语法树(AST),以生成新的代码或者修改现有代码的行为。
本文带你从头自定义属性宏,用于自定义评估函数执行占用时间。
创建项目工程
首先创建主体项目 foo2, 然后进入该项目目录中,再创建macro_lib 项目,我们在子项目中实现属性宏代码。
# 创建主体工程
cargo new foo2
cd foo2
cargo new macro_lib --lib
项目树结构大致如下:
├── src
│ └── main.rs
├── macro_lib
│ ├── src
│ │ ├── log_duration.rs
│ │ └── lib.rs
│ ├── Cargo.toml
│ └── Cargo.lock
├── Cargo.toml
└── Cargo.lock
在主项目的cargo.toml中增加子项目依赖:
[dependencies]
macro_lib = { path = "./macro_lib" }
声明属性宏
我们在子项目的lib.rs中定义函数,并使用宏进行标识,告诉编译器该函数是宏声明:
// macro_lib/src/lib.rs
#[proc_macro_attribute]
pub fn log_duration(args: TokenStream, item: TokenStream) -> TokenStream {
log_duration_impl(args, item)
}
对于属性宏定义,函数名很重要,因为名称就是属性宏的名称。正如你所看到的,这需要两个不同的参数。第一个是传递给属性宏的参数,第二个是属性宏的目标。
为了实现于声明分离,我们定义新的文件实现log_duration_impl函数:
touch src/log_duration.rs
实现log_duration
属性宏
我将首先给你完整的实现,然后我将分解到目前为止我还没有使用的部分:
// macro_lib/src/log_duration.rs
use proc_macro::