Подтвердить что ты не робот

Как использовать макрос в файлах модулей?

У меня есть два модуля в отдельных файлах в одном ящике, где ядро ​​имеет macro_rules. Я хочу использовать макросы, определенные в одном модуле в другом модуле.

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

В настоящее время я попал в ошибку компилятора "macro undefined: 'my_macro'"... что имеет смысл; макросистема запускается перед модульной системой. Как мне обойти это?

4b9b3361

Ответ 1

Макросы внутри одного ящика

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

bar!();    // works

Если вы хотите использовать макрос в том же ящике, модуль, в котором определен ваш макрос, нуждается в атрибуте #[macro_use].

Макросы можно использовать только после того, как они были определены. Это означает, что это не работает:

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

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

Макросы через ящики

Чтобы использовать ваши macro_rules! макрос из других ящиков, сам макрос нуждается в атрибуте #[macro_export]. Импортирующий ящик может затем импортировать макрос с помощью use crate_name::macro_name; ,

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


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

foo!();

Примечание: макросы всегда живут на верхнем уровне ящика; так что даже если foo будет внутри mod bar {}, user ящик все равно должен будет написать use util::foo; и не use util::bar::foo; ,

(До Rust 2018 вы должны были импортировать макрос из других ящиков, добавив атрибут #[macro_use] в #[macro_use] extern crate util; это импортировало бы все макросы из util. Альтернативно, #[macro_use(cat, dog)] может быть используется только для импорта макросов cat и dog. Этот синтаксис больше не нужен.)


Более подробная информация доступна на языке программирования Rust.

Ответ 2

Этот ответ устарел, как у Rust 1.1.0-stable.


Вам нужно добавить #![macro_escape] вверху macros.rs и включить его с помощью mod 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

В будущем,

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

Ответ 3

Добавление #![macro_use] в начало файла, содержащего макросы, приведет к выталкиванию всех макросов в main.rs.

Например, допустим, что этот файл называется node.rs:

#![macro_use]

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

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

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

Ваш main.rs будет выглядеть примерно так:

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

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

Наконец, скажем, у вас есть файл с именем toad.rs, который также требует этих макросов:

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

pub fn a_thing() {
  test!();

  node::fun_times();
}

Обратите внимание, что после того, как файлы втянуты в main.rs с помощью mod, остальные ваши файлы имеют доступ к ним с помощью ключевого слова use.