Tengo dos módulos en archivos separados dentro de la misma caja, donde la caja se ha macro_ruleshabilitado. Quiero usar las macros definidas en un módulo en otro 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?
Actualmente encuentro el error del compilador " macro undefined: 'my_macro'" ... que tiene sentido; el sistema de macros se ejecuta antes que el sistema de módulos. ¿Cómo soluciono eso?
module
rust
rust-macros
usuario
fuente
fuente

module::my_macro!()?Respuestas:
Macros dentro de la misma caja
#[macro_use] mod foo { macro_rules! bar { () => () } } bar!(); // worksSi desea utilizar la macro en la misma caja, el módulo en el que está definida su macro necesita el atributo
#[macro_use].Las macros solo se pueden utilizar después de que se hayan definido. Esto significa que esto no funciona:
bar!(); // ERROR: cannot find macro `bar!` in this scope #[macro_use] mod foo { macro_rules! bar { () => () } }Macros en cajas
Para usar su
macro_rules!macro de otras cajas, la macro en sí necesita el atributo#[macro_export]. La caja de importación puede importar la macro a través deuse crate_name::macro_name;.Caja
util#[macro_export] macro_rules! foo { () => () }Caja
useruse util::foo; foo!();Tenga en cuenta que las macros siempre viven en el nivel superior de una caja; así que incluso si
fooestuviera dentro de unmod bar {}, lausercaja todavía tendría que escribiruse util::foo;y nouse util::bar::foo;.Antes de Rust 2018, tenía que importar macro de otras cajas agregando el atributo
#[macro_use]a laextern crate util;declaración. Eso importaría todas las macros deutil. Alternativamente,#[macro_use(cat, dog)]podría usarse para importar solo las macroscatydog. Esta sintaxis ya no debería ser necesaria.Hay más información disponible en el capítulo sobre macros de The Rust Programming Language .
fuente
macrosyfoo(que usa una macro demacros), y los enumera en orden alfabético en sus lib.rs o main.rs, foo se cargará antes que las macros y el código no se compilará.#[macro_use]atributo debe estar en cada módulo y módulo principal, etc. hasta que llegue al punto en el que necesite usarlo.#[macro_use]y se declaró primero en lib.rs - todavía no funcionó. La respuesta de @ Ten ayudó y agregué#[macro_use]a la parte superior de lib.rs, luego funcionó. Pero todavía no estoy seguro de cuál es la mejor práctica, ya que leí aquí que "No importa macros de otros módulos; exporta la macro desde el módulo de definición"Esta respuesta está desactualizada a partir de Rust 1.1.0-estable.
Debe agregarlo
#![macro_escape]en la parte superiormacros.rse incluirlo usandomod macros;como se menciona en la Guía 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 hiPara futura referencia,
$ rustc -v rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)fuente
#[macro_export]atributo es innecesario aquí. Solo es necesario si la macro debe exportarse a usuarios externos de cajas. Si la macro solo se usa dentro de la caja,#[macro_export]no es necesaria.something.rsarchivo usa otros módulos, por ejemplomod foobar;, con , y estefoobarmódulo usa las macros demacro.rs, entonces debe ponermod macro;antesmod foobar;para que el programa se compile. Algo menor, pero esto no es una OMI obvia.Agregar
#![macro_use]a la parte superior de su archivo que contiene macros hará que todas las macros se incorporen a main.rs.Por ejemplo, supongamos que este archivo se llama node.rs:
#![macro_use] macro_rules! test { () => { println!("Nuts"); } } macro_rules! best { () => { println!("Run"); } } pub fn fun_times() { println!("Is it really?"); }Su main.rs se vería en algún momento como el siguiente:
mod node; //We're using node.rs mod toad; //Also using toad.rs fn main() { test!(); best!(); toad::a_thing(); }Finalmente, digamos que tiene un archivo llamado toad.rs que también requiere estas macros:
use node; //Notice this is 'use' not 'mod' pub fn a_thing() { test!(); node::fun_times(); }Tenga en cuenta que una vez que los archivos se introducen en main.rs con
mod, el resto de sus archivos tienen acceso a ellos a través de lausepalabra clave.fuente
#![macro_use]declaración está DENTRO del macro-módulo, no fuera. La#![...]sintaxis corresponde a tener atributos que se aplican a los ámbitos que los contienen, por ejemplo#]; requeriría semánticamente que el compilador habilite ciertas características en elementos específicos en una caja, en lugar de la caja raíz completa). Entonces, como dijo @LukeDupin, el sistema de módulos es un desastre, aunque quizás por una razón diferente a la primera vista.Me encontré con el mismo problema en Rust 1.44.1, y esta solución funciona para versiones posteriores (se sabe que funciona para Rust 1.7).
Digamos que tiene un nuevo proyecto como:
En main.rs , debe anotar que está importando macros desde la fuente, de lo contrario, no funcionará.
#[macro_use] mod memory; mod chunk; fn main() { println!("Hello, world!"); }Entonces, en memory.rs puede definir las macros y no necesita anotaciones:
macro_rules! grow_capacity { ( $x:expr ) => { { if $x < 8 { 8 } else { $x * 2 } } }; }Finalmente, puede usarlo en chunk.rs , y no necesita incluir la macro aquí, porque está hecho en main.rs:
grow_capacity!(8);La respuesta votada a favor me causó confusión, con este documento como ejemplo , también sería útil.
fuente
#[macro_use] mod foo {.#[macro_use]en definición. El compilador no dice que esté fuera de lugar.