Rust 過程巨集

2021-10-04 19:22:28 字數 3246 閱讀 8414

一、新增過程巨集依賴庫

1、過程巨集,類似其他語言的執行時反射機制

2、官方的過程巨集庫為proc_macro,不推薦直接使用

3、推薦更友好的synquoteproc_macro2這3個庫

4、過程巨集,必須寫在單獨的lib型別的crate中

[lib]

proc-macro = true

[dependencies]

syn = "1.0.17"

quote = "1.0.3"

proc-macro2 = "1.0.10"

導入庫

extern crate proc_macro;

use syn::;

use quote::*;

use proc_macro::tokenstream;

二、使用syn解析derive過程巨集的詞條流,生成deriveinput結構體

1、deriveinput結構體,字段如下

pub struct deriveinput
示例結構體

struct mystructwhere t: sized
2、使用巨集parse_macro_input!解析輸入的詞條流tokenstream,並列印結構體名稱

#[proc_macro_derive(mytest)]

pub fn derive_my_test(input: tokenstream) -> tokenstream ", derive_input.ident.to_token_stream());

// ...

}

3、解析泛型相關的幾個詞條,並列印

let (impl_generics, ty_generics, where_clause) = derive_input.generics.split_for_impl();

println!("impl_generics: {}", impl_generics.to_token_stream()); // < t >

println!("ty_generics: {}", ty_generics.to_token_stream()); // < t >

println!("where_clause: {}", where_clause.to_token_stream()); // where t : sized

4、解析結構體欄位,可能是有名字段,也可能是無名字段,並列印

match derive_input.data ) {}: {}", index, field.ident.to_token_stream(), field.ty.to_token_stream())}},

// field: (0) : string

// field: (1) : vec < u8 >

// field: (2) : t

syn::fields::unnamed(ref fields_unnamed) => ): {}", index, field.ty.to_token_stream())}},

syn::fields::unit => ,

},_ => (),

}

5、給derive新增屬性(attributes),列印deriveinput中的attrs

pub struct attribute
// 實現方

#[proc_macro_derive(showstruct, attributes(optiondesc))]

// 使用方

#[derive(showstruct)]

#[optiondesc(ctx = "this is a description")]

// 列印具體的解析資訊

let _attr: vec<()> = derive_input.attrs.iter().map(|x| , tokens: {}", x.path.to_token_stream(), x.tokens);

}).collect();

6、檢視結構體的可見性,並列印

match derive_input.vis ", vp.to_token_stream()); // pub

},syn::visibility::crate(ref vc) => ", vc.to_token_stream()); // crate

},syn::visibility::restricted(ref vr) => ", vr.to_token_stream()); // pub (***)

},_ => ", "inherited"); // inherited

},}

7、建立新的ident,比如函式名稱

let struct_name = derive_input.ident;

let fn_name = syn::ident::new("show_struct", proc_macro2::span::call_site());

三、使用quote!巨集,生成proc_macro2的詞條流

1、示例**

let proc_macro2_token_stream = quote! (

impl #impl_generics #struct_name #ty_generics #where_clause });

tokenstream::from(proc_macro2_token_stream)

// proc_macro2_token_stream.into()

2、使用#***捕獲可以to_token_stream()的詞條

Rust 巨集筆記

rust 巨集筆記 這篇文章說的是?rust 的巨集。宣告巨集 declarative macro 和過程巨集 procedural macro 前者指的是用某種語法直接宣告出的巨集。後者是對應直接生成抽象語法樹的過程的巨集。直覺上過程巨集更隱式,更全能 宣告巨集更可讀,更直接。如何定義宣告巨集?現...

rust巨集的復用

由於這一部分別人已經寫過就不多贅述,放個鏈結 假如我們在crate中想要寫乙個巨集,為了美觀將其單獨放在了乙個檔案中,假設叫macros.rs,如下圖所示 如果我們想在同一層級的node.rs中使用這個巨集,那麼需要做的就是在這個巨集前加上 macro export 並且在lib.rs中新增 mac...

Rust中巨集的理解

巨集相比函式是相對難以理解的,更加難以掌握,編寫理解以及除錯都很有困難。但它的存在肯定是有它比較獨特的地方的。相比函式,巨集是用來生成 的,在呼叫巨集的地方,編譯器會先將巨集進行展開,生成 然後再編譯展開後的 在rust中,函式是不接受任意多個引數的,巨集可以辦到。巨集定義格式macro rules...