Rust 1.7.0 macro宏的复用 #[macro_use]的使用方法

Rust 1.7.0 中的宏使用范围包含三种情况:

第一种情况是宏定义在当前文件里。这个文件可能是 crate 默认的 module,也可能是随意的 module 模块。

另外一种情况是宏定义在当前 crate 。可是不是在当前文件里,而是其它 module 模块中。

第三种情况是宏定义在其它的 crate 中。或者其它的 crate 子模块中。

使用#[macro_use] 能够使被注解的module模块中的宏应用到当前作用域中。或者凝视crate中的宏应用到当前crate作用域中。

第一种情况的样例:

macro_rules! say_hello{
   ()=>(
       println!("Hello");
   )
}

fn main(){
    say_hello!();
}

另外一种情况:

  • 先创建一个新文件 macros.rs ,定义一个宏 say_bonjour
macro_rules! say_bonjour{
   ()=>(
       println!("Bonjour");
   )
}
  • 使用
#[macro_use]
pub mod macros;

macro_rules! say_hello{
   ()=>(
       println!("Hello");
   )
}

fn main(){
    say_hello!();
    say_bonjour!();
}
  • 假设没有 #[macro_use] 编译会出现

    error: macro undefined: ‘say_bonjour!’

第三种情况:凝视在外部 crate 的语句

  1. 创建 log 项目

    cargo new log
    
  2. 在 log 项目中,lib.rs 是入口,在lib.rs中定义 macors 模块。

.
.
.
#[macro_use]
mod macros;
.
.
.

然后,创建相应mod macros 的 macros.rs 文件 vi src/macros.rs

声明宏 log、error、warn、info,在每一个宏定义前面加入 #[macro_export]凝视。表示这些宏能够被外部的 crate 使用。

.
.
.
#[macro_export]
macro_rules! log {
    ...
}

#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Error, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Error, $($arg)*);
    )
}

#[macro_export]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Warn, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Warn, $($arg)*);
    )
}


#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Info, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Info, $($arg)*);
    )
}


.
.
.

使用:引入 log crate的时候,注明#[macro_use]

#[macro_use]
extern crate log;

.
.
.

if !shutdown.load(Ordering::SeqCst) {
                        info!("ConnectionHandler: read timed out ({:?}). Server not shutdown, so \
                               retrying read.",
                              err);
                        continue;
                    } else {
                        info!("ConnectionHandler: read timed out ({:?



}). Server shutdown, so \ closing connection.", err); break; } . . .