2019-09-24
Rustのmacroをモジュール化して、別のモジュールから呼ぼうと思ったらうまくいかなかった。
日本語の記事があまりなかったのと、自分の備忘録ようにメモを残しておく。
rustのバージョンは1.27.0
参考 https://github.com/rust-lang/book/issues/401
マクロの書き方とか、rustのimport周りは意外と日本語記事があったので、そっちを参考に
ファイル構成
lib.rsでmodをまとめて、main.rsで呼ぶようなファイル構成にする。 このようにしておくと、main.rsのなかでmodを宣言しなくてよくなるし、また誰が誰を公開しているかわかりやすくなる(たぶん)。
crate/
src/
main.rs
lib.rs
mod1/
mod.rs
macro.rs
mod2/
mod.rs
macro_run.rs
この時、main.rsを実行すると、macro_run.rsの中の関数が呼ばれ、この関数内でmacro.rsに定義してあるマクロが呼び出されるとする。
簡単に言うと、モジュール間に跨ったマクロ呼び出しが行いたい。
書き方
main.rsでは、macro_run内にあるrun関数を呼ぶ。
// main.rs
extern crate rust_test2;
use rust_test2::mod2::macro_run;
fn main() {
macro_run::run();
}
run関数内では、foo!というマクロを使う。
// macro_run.rs
#[macro_use]
use mod1::macro_test::*;
pub fn run() {
let foo = foo!(1);
println!("{}",foo);
}
fooマクロは、引数をそのまま返す単純なマクロ。
// macro.rs
#[macro_use]
macro_rules! foo {
($e: expr) => {
$e
}
}
macro_useをつける。
// mod1/lib.rs
#[macro_use]
pub mod macro_test;
ここのlibにもmacro_useが必要。
// lib.rs
#[macro_use]
pub mod mod1;
pub mod mod2;
次のように#[macro use]の順番が入れ変わるとだめ (参考:https://www.ncameron.org/blog/macros-in-rust-pt4/)
// lib.rs
pub mod mod2;
#[macro_use]
pub mod mod1;
まとめ
- #[macro_use]をいっぱいかく
- lib.rsに書く順番が大切
- コードの一部はネットの情報としてあったが、コードの全体がわからずハマったので全体をgithubにあげておく