Saya memiliki dua modul dalam file terpisah dalam peti yang sama, di mana peti telah macro_rules
diaktifkan. Saya ingin menggunakan makro yang ditentukan dalam satu modul di modul lain.
// 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?
Saat ini saya menemukan kesalahan kompilator " macro undefined: 'my_macro'
" ... yang masuk akal; sistem makro berjalan sebelum sistem modul. Bagaimana cara mengatasinya?
module
rust
rust-macros
pengguna
sumber
sumber
module::my_macro!()?
Jawaban:
Makro dalam peti yang sama
#[macro_use] mod foo { macro_rules! bar { () => () } } bar!(); // works
Jika Anda ingin menggunakan makro di peti yang sama, modul yang ditentukan makro Anda membutuhkan atribut
#[macro_use]
.Makro hanya dapat digunakan setelah ditentukan. Ini berarti ini tidak berhasil:
bar!(); // ERROR: cannot find macro `bar!` in this scope #[macro_use] mod foo { macro_rules! bar { () => () } }
Makro melintasi peti
Untuk menggunakan
macro_rules!
makro Anda dari peti lain, makro itu sendiri membutuhkan atribut#[macro_export]
. Peti pengimpor kemudian dapat mengimpor makro melaluiuse crate_name::macro_name;
.Peti
util
#[macro_export] macro_rules! foo { () => () }
Peti
user
use util::foo; foo!();
Perhatikan bahwa makro selalu berada di level teratas dari sebuah peti; jadi meskipun
foo
akan berada di dalam amod bar {}
,user
peti itu masih harus menulisuse util::foo;
dan tidakuse util::bar::foo;
.Sebelum Rust 2018, Anda harus mengimpor makro dari peti lain dengan menambahkan atribut
#[macro_use]
keextern crate util;
pernyataan tersebut. Itu akan mengimpor semua makro dariutil
. Atau,#[macro_use(cat, dog)]
dapat digunakan untuk hanya mengimpor makrocat
dandog
. Sintaks ini seharusnya tidak diperlukan lagi.Informasi lebih lanjut tersedia di bab Bahasa Pemrograman Rust pada makro .
sumber
macros
danfoo
(yang menggunakan makro darimacros
), dan Anda mencantumkannya dalam urutan abjad di lib.rs atau main.rs, foo akan dimuat sebelum makro dan kode tidak akan dikompilasi.#[macro_use]
atribut harus ada di setiap modul dan modul induk, dll .. hingga mencapai titik di mana Anda perlu menggunakannya.#[macro_use]
dan dideklarasikan pertama kali di lib.rs - masih tidak berfungsi. Jawaban @ Ten membantu dan saya menambahkan#[macro_use]
ke bagian atas lib.rs - kemudian berhasil. Tapi saya masih tidak yakin apa praktik terbaiknya karena saya membaca di sini bahwa "Anda tidak mengimpor makro dari modul lain; Anda mengekspor makro dari modul penentu"Jawaban ini sudah usang karena Rust 1.1.0-stable.
Anda perlu menambahkan
#![macro_escape]
di bagian atasmacros.rs
dan memasukkannya menggunakanmod macros;
seperti yang disebutkan di Panduan Makro .$ 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
Untuk referensi di masa mendatang,
$ rustc -v rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)
sumber
#[macro_export]
atribut tidak diperlukan di sini. Ini hanya diperlukan jika makro harus diekspor ke pengguna eksternal. Jika makro hanya digunakan di dalam peti,#[macro_export]
tidak diperlukan.something.rs
file Anda menggunakan modul lain, misalnya denganmod foobar;
, danfoobar
modul ini menggunakan makro darimacro.rs
, maka Anda harus meletakkanmod macro;
sebelumnyamod foobar;
agar program dapat dikompilasi. Hal kecil, tapi ini bukan IMO yang jelas.Menambahkan
#![macro_use]
ke bagian atas file Anda yang berisi makro akan menyebabkan semua makro ditarik ke main.rs.Misalnya, file ini bernama node.rs:
#![macro_use] macro_rules! test { () => { println!("Nuts"); } } macro_rules! best { () => { println!("Run"); } } pub fn fun_times() { println!("Is it really?"); }
Rumah utama Anda akan terlihat seperti berikut ini:
mod node; //We're using node.rs mod toad; //Also using toad.rs fn main() { test!(); best!(); toad::a_thing(); }
Terakhir, katakanlah Anda memiliki file bernama toad.rs yang juga membutuhkan makro berikut:
use node; //Notice this is 'use' not 'mod' pub fn a_thing() { test!(); node::fun_times(); }
Perhatikan bahwa setelah file ditarik ke main.rs dengan
mod
, sisa file Anda memiliki akses ke sana melaluiuse
kata kunci.sumber
#![macro_use]
pernyataan DI DALAM makro-modul, bukan di luar. The#![...]
sintaks bersesuaian untuk memiliki atribut berlaku untuk lingkup yang mengandung mereka, misalnya#![feature(...)]
(jelas ini tidak akan masuk akal jika ditulis sebagai#[feature(...)]
, itu semantik akan mengharuskan compiler mengaktifkan fitur tertentu pada item tertentu dalam peti, bukan seluruh akar peti). Jadi, seperti yang dikatakan @LukeDupin, sistem modulnya berantakan, meskipun mungkin karena alasan yang berbeda dari pada pandangan pertama.Saya telah menemukan masalah yang sama di Rust 1.44.1, dan solusi ini berfungsi untuk versi yang lebih baru (dikenal berfungsi untuk Rust 1.7).
Katakanlah Anda memiliki proyek baru sebagai:
Di main.rs , Anda perlu memberi keterangan bahwa Anda mengimpor makro dari sumber, jika tidak, itu tidak akan berhasil untuk Anda.
#[macro_use] mod memory; mod chunk; fn main() { println!("Hello, world!"); }
Jadi di memory.rs Anda dapat menentukan makro, dan Anda tidak memerlukan anotasi:
macro_rules! grow_capacity { ( $x:expr ) => { { if $x < 8 { 8 } else { $x * 2 } } }; }
Akhirnya Anda bisa menggunakannya di chunk.rs , dan Anda tidak perlu menyertakan makro di sini, karena sudah selesai di main.rs:
grow_capacity!(8);
The jawaban upvoted menyebabkan kebingungan bagi saya, dengan doc ini dengan contoh , akan membantu juga.
sumber
#[macro_use] mod foo {
.#[macro_use]
definisi. Compiler tidak mengatakan itu salah tempat.