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;
                    }
   .
   .
   .
时间: 2024-08-10 19:18:37

Rust 1.7.0 macro宏的复用 #[macro_use]的使用方法的相关文章

Rust 1.7.0的macro宏-语法分析和使用举例

macro 宏的概念在很多语言中都有. 通常情况下,宏的机制是在预编译阶段对已经定义的宏进行替换或者 expanded 展开 ,即:把宏按照名称替换成宏的内容. Rust 中的宏,与众不同! Rust中的宏,也是在预编译阶段进行处理.宏不仅仅是替换内容和展开,还可以像功能函数一样,接收参数.调用其他的宏. 一.简单的宏 宏的名称和功能函数名称很像,只不过在函数名称后面有一个叹号! 一个简单的宏定义和调用: macro_rules! say_hello{ ()=>( println!("He

转 freemarker macro(宏)的使用

有人说用freemarker,但没有用到它的宏(macro),就=没有真正用过freemarker.说的就是宏是freemarker的一大特色. 宏的定义可以查看相关的文档,里面介绍得很清楚,下面来看看它的一个用法. /WEB-INF/template/common/common.ftl: <#macro html title>         <head>        <meta http-equiv="Content-Type" content=&q

do{...}while(0)在宏定义中的作用

如果你是一名C程序员,你肯定熟悉宏,它们非常的强大,如果正确使用可以让你的工作事半功倍.然后,如果你在定义宏时,很随意没有认真检查,那么它们可能使得你发狂,浪费N多时间.在很多C程序中,你可能看到许多看起来不是那么直接的较为特殊的宏定义.下面就是一个例子: 1 #define _set_taks_state(tsk, state_value) 2 do{tsk->state = state_value;}while(0) 在Linux内核和其他一些著名的C库中有许多使用do{...}while(

Rust 1.9.0 发布

2016年5月26日 Rust 1.9.0 发布. http://blog.rust-lang.org/2016/05/26/Rust-1.9.html

do...while(0)在宏定义中的巧妙用法

大家都知道,do-while(condition)可以表示循环,但你有没有遇到在一些宏定义中可以不用循环的地方,也用到了 do-while.比如: #define DELETE_POINTER(p) do { if(NULL != p) delete p; p = NULL; }while(0) 这时,do-while(0)的功能就不仅仅是循环了,这是do..while(0)的一种巧妙用法.它有以下几种功能: 1.在后面要加分号,使调用如同函数:调用如下: int* p = new int(5)

Rust 1.8.0 发布

2016年4月14日 Rust 1.8.0 发布. http://blog.rust-lang.org/2016/04/14/Rust-1.8.html

Rust 1.7.0 语法基础 标识符(ident)和分隔符的约束

一.标识符 identifier 是标识符,在Rust语法中简写为 ident . ident 是由任意个非空的unicode字符组成. 举例: 在 attribute 语法中,有 meta_item : ident [ '=' literal | '(' meta_seq ')' ] ? ; 实际使用如下: #![crate_type = "lib"] #![allow(dead_code)] #![feature(intrinsics, lang_items)] #[test] 上

[Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法

前面有几条都讲过关于Array.prototype的标准方法.这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array. arguments对象 在22条中提到的函数arguments对象.它是一个类数组对象,并不是一个标准的数组,所以无法使用数组原型中的方法,因此无法使用arguments.forEach这样的形式来遍历每一个参数.这里我们必须使用call方法来对使用forEach方法. function highlight(){ [].forEach.call(argume

php在数字前面补0得到固定长度数字的两种方法

比较基础,其实两个内置函数都能实现. 1  sprintf 语法: string sprintf(string format, mixed [args]...); 返回值: 字符串 函数种类: 资料处理 本函数用来将字符串格式化.参数 format 是转换的格式,以百分比符号 % 开始到转换字符为止.而在转换的格式间依序包括了 填空字符.0 的话表示空格填 0:空格是默认值,表示空格就放着. 对齐方式.默认值为向右对齐,负号表向左对齐. 字段宽度.为最小宽度. 精确度.指在小数点后的浮点数位数.