我在同一个箱子中的两个单独文件中有两个模块,其中箱子启用了macro_rules
。我想在另一个模块中使用一个模块中定义的宏。
// macros.rs
#[macro_export] // or not? is ineffectual for this, afaik
macro_rules! my_macro(...)
// something.rs
use macros;
// use macros::my_macro; <-- unresolved import (for obvious reasons)
my_macro!() // <-- how?
我目前遇到编译器错误“macro undefined: 'my_macro'
”...这是有道理的;宏系统在模块系统之前运行。我该如何解决这个问题?
#[macro_use]
mod foo {
macro_rules! bar {
() => ()
}
}
bar!(); // works
如果要在同一个包中使用宏,则定义宏的模块需要属性#[macro_use]
。
宏只能在定义后使用。这意味着这不起作用:
bar!(); // ERROR: cannot find macro `bar!` in this scope
#[macro_use]
mod foo {
macro_rules! bar {
() => ()
}
}
要使用来自其他包装箱的macro_rules!
宏,宏本身需要属性#[macro_export]
。然后导入包可以通过use crate_name::macro_name;
导入宏。
// --- Crate `util` ---
#[macro_export]
macro_rules! foo {
() => ()
}
// --- Crate `user` ---
use util::foo;
foo!();
注意:宏总是位于箱子的顶层;即使foo
将在mod bar {}
内,user
箱仍然必须写use util::foo;
而不是use util::bar::foo;
。
(在Rust 2018之前,您必须通过将属性#[macro_use]
添加到extern crate util;
语句来从其他包中导入宏。这将从util
导入所有宏。或者,#[macro_use(cat, dog)]
可用于仅导入宏cat
和dog
。此语法不应该是必要的。)
有关更多信息,请访问The Rust Programming Language。
从Rust 1.1.0-stable开始,这个答案已经过时了。
你需要在#![macro_escape]
的顶部添加macros.rs
并使用mod macros;
中提到的Macros Guide包含它。
$ cat macros.rs
#![macro_escape]
#[macro_export]
macro_rules! my_macro {
() => { println!("hi"); }
}
$ cat something.rs
#![feature(macro_rules)]
mod macros;
fn main() {
my_macro!();
}
$ rustc something.rs
$ ./something
hi
备查,
$ rustc -v
rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)
将#![macro_use]
添加到包含宏的文件顶部将导致所有宏被拉入main.rs.
例如,假设此文件名为node.rs:
#![macro_use]
macro_rules! test {
() => { println!("Nuts"); }
}
macro_rules! best {
() => { println!("Run"); }
}
pub fn fun_times() {
println!("Is it really?");
}
您的主要人员会看起来像下面这样:
mod node; //We're using node.rs
mod toad; //Also using toad.rs
fn main() {
test!();
best!();
toad::a_thing();
}
最后,假设您有一个名为toad.rs的文件,它还需要这些宏:
use node; //Notice this is 'use' not 'mod'
pub fn a_thing() {
test!();
node::fun_times();
}
请注意,一旦使用mod
将文件拖入main.rs,其余文件就可以通过use
关键字访问它们。