一、新增過程巨集依賴庫
1、過程巨集,類似其他語言的執行時反射機制2、官方的過程巨集庫為
proc_macro
,不推薦直接使用3、推薦更友好的
syn
、quote
和proc_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...