मैं मॉड्यूल फ़ाइलों में मैक्रो का उपयोग कैसे करूं?


105

मेरे पास एक ही टोकरे के भीतर अलग-अलग फाइलों में दो मॉड्यूल हैं, जहां टोकरा 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'" ... जो समझ में आता है मारा ; मॉड्यूल सिस्टम से पहले मैक्रो सिस्टम चलता है। मैं उसके आसपास कैसे काम करूं?


कंधे, 'आप का उपयोग करेंmodule::my_macro!()?
u_mulder

2
nope (afaik नहीं) - मॉड्यूल उपसर्ग को कथित रूप से अनदेखा किया जाता है (संकलक संदेश के अनुसार)।
उपयोगकर्ता

जवाबों:


144

उसी टोकरे के भीतर मैक्रों

#[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;

टोकरा util

#[macro_export]
macro_rules! foo {
    () => ()
}

टोकरा user

use util::foo;

foo!();

ध्यान दें कि मैक्रो हमेशा एक टोकरे के शीर्ष-स्तर पर रहते हैं; तो भी अगर टोकरा fooअंदर होगा mod bar {}, userतब भी टोकरा लिखना होगा use util::foo;और नहीं use util::bar::foo;

Rust 2018 से पहले, आपको स्टेटमेंट में विशेषता जोड़कर मैक्रो को अन्य बक्से से आयात #[macro_use]करना होगा extern crate util;। इससे सभी मैक्रोज़ आयात होंगे util। वैकल्पिक रूप से, #[macro_use(cat, dog)]केवल मैक्रोज़ आयात करने के लिए इस्तेमाल किया जा सकता है catऔर dog। यह वाक्यविन्यास अब आवश्यक नहीं होना चाहिए।

मैक्रों पर द रस्ट प्रोग्रामिंग लैंग्वेज चैप्टर में अधिक जानकारी उपलब्ध है ।


32
"मैक्रोज़ का उपयोग केवल तब ही किया जा सकता है जब उन्हें परिभाषित किया गया हो।" - यह महत्वपूर्ण है क्योंकि आप उस त्रुटि में भी भाग सकते हैं जब आपने अन्य सभी चीजों को सही ढंग से उल्लेख किया हो। उदाहरण के लिए, यदि आपके पास मॉड्यूल हैं macrosऔर foo(जो कि मैक्रो का उपयोग करता है macros), और आप उन्हें अपने lib.rs या main.rs में वर्णानुक्रम में सूचीबद्ध करते हैं, तो फू को मैक्रोज़ से पहले लोड किया जाएगा और कोड संकलित नहीं होगा।
neverfox

9
^ प्रो टिप - यह पूरी तरह से मुझे मिला
semore_1267

6
यह भी ध्यान दें कि आंतरिक रूप से मैक्रोज़ का उपयोग करने के लिए, #[macro_use]विशेषता हर मॉड्यूल और माता-पिता मॉड्यूल आदि पर होनी चाहिए।
दस

1
यह जवाब मेरे काम नहीं आया। जिस मॉड्यूल ने मैक्रो की घोषणा की थी #[macro_use]और उसे पहले lib.rs में घोषित किया गया था - फिर भी काम नहीं किया। @ दस के जवाब ने मदद की और मैंने #[macro_use]lib.rs के शीर्ष पर जोड़ा - तब यह काम किया। लेकिन मुझे अभी भी यकीन नहीं है कि सबसे अच्छा अभ्यास क्या है क्योंकि मैंने यहां पढ़ा है कि "आप अन्य मॉड्यूल से मैक्रोज़ आयात नहीं करते हैं; आप मैक्रो को परिभाषित मॉड्यूल से निर्यात करते हैं"
सोरिन बोलोस

मैं हमेशा भूल जाता हूं कि रस्ट के मैक्रोज़ मॉड्यूल के साथ कैसे काम करते हैं। यह एक भयानक प्रणाली है, और उम्मीद है कि किसी दिन बेहतर होगा।
हच मूर

21

यह उत्तर रस्ट 1.1.0-स्थिर के रूप में पुराना है।


आपको #![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)

मैं पूरी तरह से उस विशेषता को याद करूँगा। धन्यवाद!
उपयोगकर्ता

4
BTW, #[macro_export]विशेषता यहाँ अनावश्यक है। यह केवल तभी आवश्यक है जब मैक्रो को बाहरी टोकरा उपयोगकर्ताओं को निर्यात किया जाना चाहिए। यदि मैक्रो का उपयोग केवल टोकरे के अंदर किया जाता है, #[macro_export]तो इसकी आवश्यकता नहीं है।
व्लादिमीर मतावेव

1
उत्तर के लिए बहुत बहुत धन्यवाद। मैं केवल यह जोड़ना चाहता हूं कि यदि आपकी something.rsफ़ाइल अन्य मॉड्यूल का उपयोग करती है, उदाहरण के लिए mod foobar;, और यह foobarमॉड्यूल मैक्रोज़ का उपयोग करता है macro.rs, तो आपको प्रोग्राम को संकलित करने के लिए mod macro; पहले रखना होगा mod foobar;। मामूली बात है, लेकिन यह एक स्पष्ट IMO नहीं है।
conradkleinespel

2
(nb यह उत्तर अब पुराना हो गया है; मैंने लुकास द्वारा दिया गया अप-टू-डेट उत्तर स्वीकार कर लिया है)
उपयोगकर्ता

9

#![macro_use]मैक्रोज़ युक्त आपकी फ़ाइल के शीर्ष पर जोड़ने से सभी मैक्रोज़ को main.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कीवर्ड के माध्यम से उन तक पहुंचती हैं ।


मैंने और स्पष्टीकरण जोड़ा। 1.22.1 रस्टक के रूप में, यह काम करता है।
ल्यूक डुपिन

क्या आपको यकीन है? यह कहां है # [? मैक्रो_यूज़] (# नहीं [मैक्रो_यूज़]) प्रलेखित? मैं इसे नहीं ढूँढ सकता। यह यहाँ काम नहीं करता है।
मार्कस

यह काम किया जब मैंने इसे पोस्ट किया है, रस्ट की शामिल प्रणाली इतनी भयानक गड़बड़ है, इसकी पूरी तरह से यह अब और काम नहीं करता है।
ल्यूक ड्यूपिन

@ मर्कस ध्यान दें कि #![macro_use]बयान मैक्रो-मॉड्यूल के अंदर है, बाहर नहीं। #![...]होने विशेषताओं के वाक्य रचना मेल खाती है उनके युक्त स्कोप, जैसे के लिए लागू #![feature(...)](स्पष्ट रूप से इस अर्थ अगर के रूप में लिखा नहीं होगा #[feature(...)], यह अर्थ की दृष्टि से कि संकलक के बजाय पूरे जड़ टोकरा एक टोकरे में विशेष आइटम, पर कुछ सुविधाओं को सक्षम की आवश्यकता होगी)। तो, जैसा कि @LukeDupin ने कहा, मॉड्यूल सिस्टम एक गड़बड़ है, हालांकि पहली नज़र में अलग कारण से हो सकता है।
उपयोगकर्ता

मैं चाहता हूं कि इस उत्तर में उल्लेख किया गया है कि निर्माण बिल्कुल मुहावरेदार नहीं है (कि एक तरफ, मुझे उत्तर पसंद है)। इसके (गैर) -डायोमैटिकिटी के बावजूद, यह दिलचस्प है क्योंकि इसे मुहावरेदार रूप के बगल में रखने से यह स्पष्ट रूप से स्पष्ट हो जाता है कि मैक्रोज़ सामान्य निर्माणों की तुलना में एक अलग तरीके से मॉड्यूल सिस्टम के साथ बातचीत करते हैं। या यह कम से कम एक मजबूत गंध देता है (जैसा कि @Markus द्वारा दिखाया गया है कि इसके साथ एक पकड़ है)।
उपयोगकर्ता

3

मैं रूस्ट १.४४.१ में एक ही समस्या को लेकर आया हूं, और यह समाधान बाद के संस्करणों के लिए काम करता है (जिसे रस्ट १.) के लिए जाना जाता है)।

कहो कि आपके पास एक नई परियोजना है:

src/
    main.rs
    memory.rs
    chunk.rs

में main.rs , तो आप टिप्पणी करने की जरूरत है कि आप स्रोत से मैक्रोज़ आयात कर रहे हैं, अन्यथा, यह आप के लिए काम नहीं चलेगा।

#[macro_use]
mod memory;
mod chunk;

fn main() {
    println!("Hello, world!");
}

तो मैमोरी में। आप मैक्रोज़ को परिभाषित कर सकते हैं, और आपको एनोटेशन की आवश्यकता नहीं है:

macro_rules! grow_capacity {
    ( $x:expr ) => {
        {
            if $x < 8 { 8 } else { $x * 2 }
        }
    };
}

अंत में आप इसे chunk.rs में उपयोग कर सकते हैं , और आपको यहाँ मैक्रो को शामिल करने की आवश्यकता नहीं है, क्योंकि यह main.rs में किया गया है:

grow_capacity!(8);

Upvoted जवाब , मेरे लिए भ्रम का कारण के साथ उदाहरण के द्वारा इस डॉक , यह भी उपयोगी होगा।


स्वीकृत उत्तर का शाब्दिक अर्थ है कि पहले कोड ब्लॉक की पहली पंक्तियों के रूप में #[macro_use] mod foo {:।
18pm पर Shepmaster

2
@ शेपस्टर के उत्तोलक उत्तर में मैक्रोज़ और उसी स्थान पर आयात विवरण की परिभाषा है, इसलिए इसने भ्रम पैदा किया (मेरे लिए)। मैं #[macro_use]परिभाषा में उपयोग कर रहा था । कंपाइलर यह नहीं कहता कि यह गलत है।
181 पर knh190


इस उत्तर के लिए धन्यवाद! मैं स्वीकार किए गए उत्तर के रूप में अच्छी तरह से भ्रमित था और जब तक मैंने आपके स्पष्टीकरण को नहीं पढ़ा, तब तक यह पता नहीं लगा सका।
Prgrm.celeritas

1
इसके अलावा के सही क्रम रखना सुनिश्चित करें modमें main.rs। यदि आपके पास है mod chunk; mod memory;, तो मैक्रो कॉल memory.rsविफल हो जाएगा।
इन्नती
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.