这里的问题是println!("{}", file!());
在编译时而不是在运行时执行。与最近在此处给出的答案类似,您可以编辑原始函数并在其开头插入代码,这一次将在运行时执行。您仍然可以使用过程宏file!()
和module_path!()
. 这是一种macro.rs
采用这种方法的方法:
#[proc_macro_attribute]
pub fn some_attribute(_attr: TokenStream, input: TokenStream) -> TokenStream {
// prefix to be added to the function's body
let mut prefix: TokenStream = "
println!(\"Called from {:?} inside module path {:?}\",
file!(), module_path!());
".parse().unwrap();
// edit TokenStream
input.into_iter().map(|tt| {
match tt {
TokenTree::Group(ref g) // match function body
if g.delimiter() == proc_macro::Delimiter::Brace => {
// add logic before function body
prefix.extend(g.stream());
// return new function body as TokenTree
TokenTree::Group(proc_macro::Group::new(
proc_macro::Delimiter::Brace, prefix.clone()))
},
other => other, // else just forward
}
}).collect()
}
你可以在你的main.rs
:
use mylib::some_attribute;
#[some_attribute]
fn yo() -> () { println!("yo"); }
fn main() { yo(); }
请注意,代码是在函数体内部的内容之前添加的。我们本可以在最后插入它,但这会破坏返回不带分号的值的可能性。
编辑:后来意识到 OP 希望它在compile time运行。