繁体   English   中英

如何创建proc_macro_attribute?

[英]How do I create a proc_macro_attribute?

现在proc_macros 已稳定下来 ,如何创建这样的东西?

从我所看到的,可以在fn whatsitsname(attrs: TokenStream, code: TokenStream) -> TokenStream上放置#[proc_macro_attribute]批注,但是我该如何注册? 如何添加自定义属性?

Rust编译器具有相当完整的测试套件 在寻找新功能的示例时,我经常从这里开始:

$ rg -c proc_macro_attribute
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs:2
src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs:1
[... 35 other matches ...]

这是一个完整的示例:

$ tree
.
├── Cargo.toml
├── my_macro
│   ├── Cargo.toml
│   ├── src
│   │   └── lib.rs
└── src
    └── main.rs

货物清单

我们添加了对宏定义板条箱的依赖。

[package]
name = "foo"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]

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

src / main.rs

我们导入属性宏并将其添加到函数中。

#[macro_use]
extern crate my_macro;

#[log_entry_and_exit(hello, "world")]
fn this_will_be_destroyed() -> i32 {
    42
}

fn main() {
    dummy()
}

my_macro / Cargo.toml

我们将crate_type指定为proc_macro

[package]
name = "my_macro"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]

[lib]
crate_type = ["proc-macro"]

my_macro / src / lib.rs

我们将#[proc_macro_attribute]添加到应为宏的每个函数中。

extern crate proc_macro;

use proc_macro::*;

#[proc_macro_attribute]
pub fn log_entry_and_exit(args: TokenStream, input: TokenStream) -> TokenStream {
    let x = format!(r#"
        fn dummy() {{
            println!("entering");
            println!("args tokens: {{}}", {args});
            println!("input tokens: {{}}", {input});
            println!("exiting");
        }}
    "#,
            args = args.into_iter().count(),
            input = input.into_iter().count(),
    );

    x.parse().expect("Generated invalid tokens")
}

货物运行

entering
args tokens: 3
input tokens: 7
exiting

“困难”部分是将TokenStream成有用的东西,然后输出同样有用的东西。 包装箱synquote是这两项任务的当前黄金标准。 Rust编程语言宏一章以及API文档中 介绍了如何处理TokenStream

还有#[proc_macro] ,它采用以下形式的函数:

#[proc_macro]
pub fn the_name_of_the_macro(input: TokenStream) -> TokenStream

可以作为the_name_of_the_macro!(...)调用。

如果我正确理解RFC 1566 ,则您:

  • 创建一个类型为proc_macro的板条箱,即其Cargo.toml应该包含

     [lib] proc-macro = true 
  • 在该板条箱中,创建带有#[proc_macro_attribute]注释的实现。 #[proc_macro]函数的宏的#[proc_macro_derive]针对自定义函数的#[proc_macro_derive]的派生工作相同,只是它们只有一个TokenStream参数。 这些在proc_macro板条箱中定义。

    第一个令牌流是属性中的参数,第二个令牌流是带注释项的主体。

  • 然后,在要使用该宏的板条箱中,只需依赖proc_macro板条箱,并使用#[macro_use]属性( #[macro_use] extern crate …)将其导入。

那应该足够了。

本书的附录应扩展为提及#[proc_macro_derive]以外的其他proc宏类型。 可能不是错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM