我试图编写一些调试助手宏。所以我创建了一个箱子来容纳所有这些箱子,并使用phase(插件)从外部引用箱子:
#[cfg(test)]
#[phase(plugin)]
extern crate debugging;
成功将宏导出到包中。
但是,对于其中一些工具,我想从包中调用函数,例如:
#[macro_export]
macro_rules! trace(
{$($arg:tt)*} => {
{
extern crate debug;
let s = ::macros::logger(); // <---- This!
let _ = s.write_line(format_args!(::std::fmt::format, $($arg)*).as_slice());
}
};
)
使用全局命名空间,即。如果将宏放入macros.rs并从包的箱子根目录导入,则:: macros :: logger可以正常工作。
然而,当宏必须从自己的包中调用一个调用时,我在这里尝试实现的是同样的事情。
如果宏扩展正确,我相信:
let s = ::crate_name::logger();
是这样做的方法,但是宏的箱子不能以这种方式通过名称引用自己。它会产生如下错误:
src/macros.rs:52:15: 52:20 error: failed to resolve. Maybe a missing `extern crate debugging`?
src/macros.rs:52 let s = ::debugging::logger();
^~~~~
src/macros.rs:49:1: 56:2 note: in expansion of trace!
src/file.rs:26:11: 26:29 note: expansion site
......最后我们完全清楚我要做的事情:
crate debugging:
lib.rs
fn logger()
macros.rs
macro_rules! trace(...) // <--- Trying to figure out what to put here...
crate foo:
lib.rs
#[phase(plugin)] extern crate debugging;
fn test_thing() {
trace!("{}", ...); // <--- So debugging::logger() is invoked here
}
那么,有没有办法从宏中做到这一点?
答案 0 :(得分:2)
目前,正确的做法是使用类似的绝对路径,然后在原始包中进行一些重新导出,以便路径解析。
即。在lib.rs
put
mod debugging {
pub use logger;
}
将顶级函数logger
重新导出为debugging::logger
。正在进行的工作使这种方法变得更加合理,例如$crate
扩展为宏来自的箱子的名称(当在外部使用时),或者什么都没有(在内部使用时);这不一定是最终设计,但它正在改进。
答案 1 :(得分:0)
对于其他发现此问题的人,值得注意的是,您无法使用标有阶段插件的箱子。要在本地导入符号(根据接受的答案),您需要执行以下操作:
#[cfg(test)]
mod debug {
#[phase(plugin)]
extern crate debugging;
extern crate debugging;
pub use self::debugging::debug;
}
请注意双外部包装箱调试,因为通常您不希望将语法扩展模块导出为代码的一部分。