Rust_macro

Rust 的宏系统分为两大类: 声明宏 (Declarative Macros)和 过程宏 (Procedural Macros)。


1. 宏的基本概念

1.1 宏的作用

  • 代码复用 :通过宏减少重复代码。
  • 代码生成 :在编译时生成代码,减少运行时开销。
  • 领域特定语言(DSL) :通过宏创建自定义语法。

1.2 宏的分类

  • 声明宏 :通过模式匹配生成代码,使用 macro_rules! 定义。
  • 过程宏 :更灵活,允许在编译时运行 Rust 代码生成代码,分为三类:
  • 自定义派生宏 (Custom Derive Macros):为结构体或枚举自动实现 trait。
  • 类属性宏 (Attribute-like Macros):为代码块添加自定义属性。
  • 类函数宏 (Function-like Macros):像函数一样调用的宏。

2. 声明宏(Declarative Macros)

2.1 声明宏的定义

使用 macro_rules! 定义声明宏,语法如下:

1
2
3
4
5
macro_rules! macro_name {
(pattern1) => { generated_code1 };
(pattern2) => { generated_code2 };
// ...
}
  • pattern:匹配输入的语法模式。
  • generated_code:生成的代码。

2.2 示例:简单的声明宏

1
2
3
4
5
6
7
8
9
macro_rules! say_hello {
() => {
println!("Hello, world!");
};
}

fn main() {
say_hello!(); // 输出:Hello, world!
}

2.3 模式匹配与捕获

声明宏支持多种模式匹配和捕获:

  • 捕获变量$var:type,例如 $x:expr 捕获表达式。
  • 重复模式$(...)*$(...)+,用于匹配重复的输入。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
macro_rules! create_vector {
($($x:expr),*) => {
{
let mut v = Vec::new();
$(v.push($x);)*
v
}
};
}

fn main() {
let v = create_vector!(1, 2, 3);
println!("{:?}", v); // 输出:[1, 2, 3]
}

3. 过程宏(Procedural Macros)

过程宏更强大,允许在编译时运行 Rust 代码生成代码。过程宏需要单独放在一个 crate 中。

3.1 自定义派生宏(Custom Derive Macros)

派生宏用于为结构体或枚举自动实现 trait。

3.1.1 定义派生宏

使用 #[proc_macro_derive] 定义派生宏。

示例:实现一个简单的 Hello trait。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(Hello)]
pub fn hello_derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.ident;

let gen = quote! {
impl Hello for #name {
fn hello() {
println!("Hello, I am {}", stringify!(#name));
}
}
};

gen.into()
}

3.1.2 使用派生宏

1
2
3
4
5
6
7
8
use hello_macro::Hello;

#[derive(Hello)]
struct Person;

fn main() {
Person::hello(); // 输出:Hello, I am Person
}

3.2 类属性宏(Attribute-like Macros)

类属性宏允许为代码块添加自定义属性。

3.2.1 定义类属性宏

使用 #[proc_macro_attribute] 定义类属性宏。

示例:定义一个属性宏,打印函数名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

#[proc_macro_attribute]
pub fn log_function(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
let fn_name = &input.sig.ident;

let gen = quote! {
#input

println!("Function '{}' was called.", stringify!(#fn_name));
};

gen.into()
}

3.2.2 使用类属性宏

1
2
3
4
5
6
7
8
9
10
11
use log_macro::log_function;

#[log_function]
fn my_function() {
println!("Doing something...");
}

fn main() {
my_function(); // 输出:Function 'my_function' was called.
}

3.3 类函数宏(Function-like Macros)

类函数宏像函数一样调用,但可以接受任意输入。

3.3.1 定义类函数宏

使用 #[proc_macro] 定义类函数宏。

示例:定义一个类函数宏,生成一个简单的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use proc_macro::TokenStream;
use quote::quote;

#[proc_macro]
pub fn make_function(input: TokenStream) -> TokenStream {
let gen = quote! {
fn generated_function() {
println!("This is a generated function!");
}
};

gen.into()
}

3.3.2 使用类函数宏

1
2
3
4
5
6
7
8
use make_function::make_function;

make_function!();

fn main() {
generated_function(); // 输出:This is a generated function!
}

  • ai总结

Rust_macro
https://pqcu77.github.io/2025/02/19/Rust-macro/
作者
linqt
发布于
2025年2月19日
许可协议