ti-enxame.com

Como uso uma macro nos arquivos do módulo?

Eu tenho dois módulos em arquivos separados dentro do mesmo engradado, onde o engradado tem macro_rules ativado. Eu quero usar as macros definidas em um módulo em outro módulo.

// 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?

No momento, atingi o erro do compilador "macro undefined: 'my_macro' "... o que faz sentido; o sistema macro é executado antes do sistema do módulo. Como faço para contornar isso?

50
user

Macros dentro da mesma caixa

#[macro_use]
mod foo {
    macro_rules! bar {
        () => ()
    }
}

bar!();    // works

Se você deseja usar a macro na mesma caixa, o módulo em que sua macro está definida precisa do atributo #[macro_use].

As macros só podem ser usadas após serem definidas. Isso significa que isso não funciona:

bar!();  // ERROR: cannot find macro `bar!` in this scope

#[macro_use]
mod foo {
    macro_rules! bar {
        () => ()
    }
}

Macros através de caixas

Para usar sua macro macro_rules! De outras caixas, a própria macro precisa do atributo #[macro_export]. A caixa de importação pode importar a macro via use crate_name::macro_name;.

// --- Crate `util` ---
#[macro_export]
macro_rules! foo {
    () => ()
}


// --- Crate `user` ---
use util::foo;

foo!();

Nota : as macros sempre vivem no nível superior de uma caixa; portanto, mesmo que foo estivesse dentro de um mod bar {}, o engradado user ainda teria que escrever use util::foo; e nãouse util::bar::foo;.

(Antes de Rust 2018, você precisava importar macro de outras caixas, adicionando o atributo #[macro_use] À instrução extern crate util;). Isso importaria todas as macros de util. Como alternativa, #[macro_use(cat, dog)] poderia ser usada para importar apenas as macros cat e dog. Essa sintaxe não é mais necessária.)


Mais informações estão disponíveis em The Rust Programming Language .

78
Lukas Kalbertodt

Esta resposta está desatualizada em Rust 1.1.0-stable.


Você precisa adicionar #![macro_escape] no topo de macros.rs e inclua-o usando mod macros; conforme mencionado no Guia de Macros .

$ 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

Para referência futura,

$ rustc -v
rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)
15
Dogbert

Adicionando #![macro_use] na parte superior do arquivo que contém macros fará com que todas as macros sejam puxadas para main.rs.

Por exemplo, vamos supor que esse arquivo seja chamado node.rs:

#![macro_use]

macro_rules! test {
    () => { println!("Nuts"); }
}

macro_rules! best {
    () => { println!("Run"); }
}

pub fn fun_times() {
    println!("Is it really?");
}

Seu main.rs seria semelhante ao seguinte:

mod node;  //We're using node.rs
mod toad;  //Also using toad.rs

fn main() {
    test!();
    best!();
    toad::a_thing();
}

Finalmente, digamos que você tenha um arquivo chamado toad.rs que também exija essas macros:

use node; //Notice this is 'use' not 'mod'

pub fn a_thing() {
  test!();

  node::fun_times();
}

Observe que quando os arquivos são puxados para o main.rs com mod, o restante dos arquivos tem acesso a eles através da palavra-chave use.

1
Luke Dupin