简体   繁体   English

如何从rust中导出的板条箱宏引用板条箱中的函数?

[英]How do you refer to functions in a crate from an exported crate macro in rust?

I'm trying to write some debugging helper macros. 我正在尝试编写一些调试助手宏。 So I create a crate to hold all of them, and referred to the crate externally using phase(plugin): 因此,我创建了一个箱子来容纳所有箱子,并使用phase(plugin)从外部引用该箱子:

#[cfg(test)]
#[phase(plugin)]
extern crate debugging;

That successfully exports the macros into the crate. 成功将宏导出到板条箱中。

However, for some of these tools I wanted to invoke functions from the crate, for example: 但是,对于某些工具,我想从包装箱中调用函数,例如:

#[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());
    }
  };
)

Using a global namespace, ie. 使用全局名称空间,即。 ::macros::logger works if the macro is placed into macros.rs and imported from the crate root of a crate. 如果将宏放置到macros.rs中并从板条箱的板条根导入,则:: macros :: logger可以工作。

However, what I'm trying to achieve here is the same thing when the macro has to invoke a call from its own crate. 但是,当宏必须从其自己的板条箱调用调用时,我要在此处实现的目标是相同的。

If the macro expanded correctly, I believe: 如果宏正确扩展,我相信:

let s = ::crate_name::logger();

Would be the way to do it, but the crate with the macro cannot refer to itself by name in this way. 可能是这样做的方法,但是带有宏的板条箱无法以这种方式按名称引用自身。 It generates errors like: 它产生如下错误:

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

...and finally just so we're completely clear about what I'm trying to do: ...最后,这样我们就可以清楚地知道我要做什么:

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
     } 

So, is there some way to do this from a macro? 那么,是否有某种方法可以从宏执行此操作?

For now, the correct thing to do is use an absolute path like that and then do some reexports in the original crate so that path resolves. 现在,正确的做法是使用类似的绝对路径,然后在原始板条箱中进行一些重新导出,以便解析路径。

Ie in lib.rs put lib.rs

mod debugging {
    pub use logger;
}

which reexports the top level function logger as debugging::logger . 它将顶级功能loggerdebugging::logger There is work being done that makes this saner, eg $crate which expands to name of the crate from which the macro came (when used externally), or to nothing (when used internally); 正在做的工作使这种情况更聪明,例如$crate扩展为宏所来自的板条箱的名称(当在外部使用时),或者扩展为零(在内部使用时); this isn't necessarily the final design, but it is improving. 这不一定是最终设计,但正在改进。

For anyone else who finds this, it's worth noting that you cannot use from a crate marked with phase plugin. 对于任何其他发现此问题的人,值得注意的是,您不能在标有相位插件的板条箱中使用。 To import the symbols locally (as per the accepted answer), you need to do this: 要在本地导入符号(按照公认的答案),您需要执行以下操作:

#[cfg(test)]
mod debug {
  #[phase(plugin)]
  extern crate debugging;
  extern crate debugging;
  pub use self::debugging::debug;
}

Notice the double extern crate debugging, because typically you wouldn't want to export a syntax extension module as part of the code. 注意双外部箱的调试,因为通常您不希望将语法扩展模块作为代码的一部分导出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM