🍉 加载中...


Rust 语言宏(Macro)简介 😊

3 minute read

概述

宏是 Rust 语言中的元编程机制,可以在编译期间扩展代码。它们允许我们在编写代码时使用元编程技术,例如重复代码和代码自动生成。

Rust 中有二种宏:函数宏属性宏

函数宏

函数宏使用 macro_rules! 关键字定义,其可以像函数一样接收输入,并产生输出。通常情况下,它们用于生成代码,例如根据输入数据动态生成代码。函数宏可以是纯函数,也可以与外部环境交互,这种宏类似于 C/C++ 中的宏。

下面是一个函数宏的简单示例:

 1#[macro_export]
 2macro_rules! multiply {
 3    ($x:expr, $y:expr) => {
 4        $x * $y
 5    };
 6}
 7
 8fn main() {
 9    let result = multiply!(3, 4);
10    println!("{}", result); // 输出 12
11}

这个宏将两个表达式作为参数,并返回它们的乘积。在主函数中,我们调用 multiply! 宏来计算 3 * 4 并将结果打印到控制台。

属性宏

属性宏是基于 proc_macro crate 实现的。其可以被用于任何项,例如结构体、枚举和函数,可以读取和操作属性,也可以将属性转换为代码。简单来讲,其接收一个 Rust 代码块作为输入,并将其转换为新的代码块,类似于 Python 中装饰器的方式修改代码。

下面是一个属性宏的完整示例:

 1use proc_macro::TokenStream;
 2use quote::quote;
 3use syn::{parse_macro_input, DeriveInput};
 4
 5#[proc_macro_attribute]
 6pub fn my_attr(_: TokenStream, input: TokenStream) -> TokenStream {
 7    // 将 TokenStream 转化为 AST
 8    let input = parse_macro_input!(input as DeriveInput);
 9
10    // 从 AST 中获取结构体名字
11    let name = input.ident;
12
13    // 构造输出的 TokenStream
14    let expanded = quote! {
15        impl #name {
16            pub fn my_method(&self) {
17                println!("This is a method added by my_attr!");
18            }
19        }
20    };
21
22    // 将 TokenStream 转化为输出结果
23    TokenStream::from(expanded)
24}

这个属性宏会为被标记的结构体添加一个方法 my_method。使用方法如下:

1#[my_attr]
2struct MyStruct;
3
4fn main() {
5    let my_struct = MyStruct;
6    my_struct.my_method();
7}

输出结果为:

1This is a method added by my_attr!

番外

自定义派生(derive)宏是一种属性宏,用于自动实现某些 trait,例如 CloneDebug。当使用派生宏时,编译器会自动为您的结构体或枚举类型实现相关的 trait,无需手动编写代码。

终末

宏是 Rust 语言中一个强大的元编程工具,可以大大简化代码编写和重复的工作,并帮助开发者编写更加灵活和易于维护的代码。