目录

  1. 什么是 Rust 宏
  2. 为什么要使用宏
  3. 宏的类型
  4. 声明式宏的定义与使用
  5. 过程宏简介
  6. 代码示例
  7. 参考资料与出站链接

什么是 Rust 宏

Rust 宏 (Macros) 是一种元编程工具,允许在编译时生成代码。它们扩展了语言的语法,提供比函数更灵活的代码生成能力,主要分为声明式宏和过程宏。


为什么要使用宏

  • 代码复用:减少重复代码。
  • 语法扩展:创建特定领域的语法。
  • 性能:编译时展开,无运行时开销。
  • 灵活性:处理可变参数或复杂逻辑。

宏的类型

  1. 声明式宏 (Declarative Macros)
  • 使用 macro_rules! 定义。
  • 基于模式匹配,类似函数但更强大。
  1. 过程宏 (Procedural Macros)
  • 三种形式:自定义派生、属性宏、函数式宏。
  • 操作抽象语法树 (AST),需单独 crate。
  • 依赖 proc-macro 库。

声明式宏的定义与使用

  • 定义macro_rules! name { (模式) => { 展开代码 } }
  • 模式匹配
  • $var:类型:捕获变量(类型如 exprident)。
  • *+:匹配零个或多个。
  • 调用name!(参数)
macro_rules! say_hello {
    () => {
        println!("Hello!");
    };
}

过程宏简介

  • 自定义派生 (Derive):为结构体/枚举自动实现特性(如 Debug)。
  • 属性宏:修改项的定义。
  • 函数式宏:类似函数的宏。
  • 限制:需在单独 crate 中定义,依赖 proc-macro
[lib]
proc-macro = true

代码示例

声明式宏

macro_rules! vec_of {
    ($($x:expr),*) => {
        {
            let mut v = Vec::new();
            $(v.push($x);)*
            v
        }
    };
}

fn main() {
    let v = vec_of![1, 2, 3, 4];
    println!("{:?}", v);
}

运行结果:

[1, 2, 3, 4]

多模式声明式宏

macro_rules! greet {
    ($name:expr) => {
        println!("Hello, {}!", $name);
    };
    ($name:expr, $greeting:expr) => {
        println!("{}, {}!", $greeting, $name);
    };
}

fn main() {
    greet!("Alice");
    greet!("Bob", "Hi");
}

运行结果:

Hello, Alice!
Hi, Bob!

简单过程宏(自定义派生)

my_macro/Cargo.toml

[package]
name = "my_macro"
version = "0.1.0"
edition = "2021"

[lib]

proc-macro = true

[dependencies]

syn = “2.0” quote = “1.0” proc-macro2 = “1.0”

my_macro/src/lib.rs

use proc_macro::TokenStream;
use quote::quote;
use syn;

#[proc_macro_derive(Hello)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    impl_hello(&ast)
}

fn impl_hello(ast: &syn::DeriveInput) -> TokenStream {
    let name = &ast.ident;
    let gen = quote! {
        impl #name {
            pub fn say_hello(&self) {
                println!("Hello from {}", stringify!(#name));
            }
        }
    };
    gen.into()
}

主项目 Cargo.toml

[dependencies]
my_macro = { path = "./my_macro" }

main.rs

use my_macro::Hello;

#[derive(Hello)]
struct Example;

fn main() {
    let ex = Example;
    ex.say_hello();
}

运行结果:

Hello from Example

参考资料与出站链接

  1. 官方文档
  1. 学习资源
  1. 社区支持