Qt 5.11 - Using the Meta-Object Compiler (moc)

मेटा-ऑब्जेक्ट कंपाइलर (moc) का उपयोग करना




qt

मेटा-ऑब्जेक्ट कंपाइलर (moc) का उपयोग करना

मेटा-ऑब्जेक्ट कंपाइलर, moc , वह प्रोग्राम है जो Qt के C ++ एक्सटेंशन को हैंडल करता है।

moc टूल एक C ++ हैडर फ़ाइल पढ़ता है। यदि यह Q_OBJECT मैक्रो वाले एक या अधिक श्रेणी की घोषणाएँ पाता है, तो यह उन कक्षाओं के लिए मेटा-ऑब्जेक्ट कोड वाले C ++ स्रोत फ़ाइल का उत्पादन करता है। अन्य बातों के अलावा, संकेत और स्लॉट तंत्र, रन-टाइम प्रकार की जानकारी और गतिशील संपत्ति प्रणाली के लिए मेटा-ऑब्जेक्ट कोड आवश्यक है।

moc द्वारा उत्पन्न सी ++ स्रोत फ़ाइल को संकलित किया जाना चाहिए और कक्षा के कार्यान्वयन के साथ जोड़ा जाना चाहिए।

यदि आप अपने qmake बनाने के लिए qmake का उपयोग करते हैं, तो बिल्ड नियम शामिल किए जाएंगे जो आवश्यकता होने पर moc को कॉल करते हैं, इसलिए आपको सीधे moc का उपयोग करने की आवश्यकता नहीं होगी। Moc पर अधिक पृष्ठभूमि जानकारी के लिए, देखें कि Qt संकेत और स्लॉट के लिए Moc का उपयोग क्यों करता है?

प्रयोग

moc का उपयोग आम तौर पर एक इनपुट फ़ाइल के साथ किया जाता है जिसमें वर्ग घोषणाएँ होती हैं:

class MyClass : public QObject
{
    Q_OBJECT

public:
    MyClass(QObject *parent = 0);
    ~MyClass();

signals:
    void mySignal();

public slots:
    void mySlot();
};

ऊपर दिखाए गए संकेतों और स्लॉट्स के अलावा, moc भी अगले उदाहरण के रूप में ऑब्जेक्ट गुणों को लागू करता है। Q_PROPERTY () मैक्रो एक ऑब्जेक्ट प्रॉपर्टी की घोषणा करता है, जबकि Q_ENUM () क्लास के भीतर एन्यूमरेशन प्रकारों की एक सूची घोषित करता है जो प्रॉपर्टी सिस्टम के अंदर प्रयोग करने योग्य है

निम्नलिखित उदाहरण में, हम गणना प्रकार Priority की एक संपत्ति की घोषणा करते हैं जिसे priority भी कहा जाता priority और इसमें एक फ़ंक्शन priority() और एक सेट फ़ंक्शन setPriority()

class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Priority priority READ priority WRITE setPriority)
    Q_ENUMS(Priority)

public:
    enum Priority { High, Low, VeryHigh, VeryLow };

    MyClass(QObject *parent = 0);
    ~MyClass();

    void setPriority(Priority priority) { m_priority = priority; }
    Priority priority() const { return m_priority; }

private:
    Priority m_priority;
};

Q_FLAGS () मैक्रो उन झांकियों की घोषणा करता है जिनका उपयोग झंडे के रूप में किया जाना है, अर्थात एक साथ OR'd। एक अन्य मैक्रो, Q_CLASSINFO (), आपको क्लास के मेटा-ऑब्जेक्ट में अतिरिक्त नाम / मूल्य जोड़े संलग्न करने की अनुमति देता है:

class MyClass : public QObject
{
    Q_OBJECT
    Q_CLASSINFO("Author", "Oscar Peterson")
    Q_CLASSINFO("Status", "Active")

public:
    MyClass(QObject *parent = 0);
    ~MyClass();
};

moc द्वारा उत्पादित आउटपुट को आपके प्रोग्राम के अन्य C ++ कोड की तरह ही संकलित और लिंक किया जाना चाहिए; अन्यथा, बिल्ड अंतिम लिंक चरण में विफल हो जाएगा। यदि आप qmake उपयोग qmake , तो यह स्वचालित रूप से किया जाता है। जब भी qmake चलाया जाता है, यह प्रोजेक्ट की हेडर फ़ाइलों को पार्स करता है और उन फ़ाइलों के लिए moc आह्वान करने के लिए नियम बनाता है जिनमें Q_OBJECT मैक्रो होता है।

यदि वर्ग घोषणा फ़ाइल myclass.h में पाई जाती है, तो moc आउटपुट को moc_myclass.cpp नामक फ़ाइल में रखा जाना चाहिए। इस फ़ाइल को हमेशा की तरह संकलित किया जाना चाहिए, जिसके परिणामस्वरूप ऑब्जेक्ट फ़ाइल, उदाहरण के लिए, विंडोज पर moc_myclass.obj । इस ऑब्जेक्ट को तब ऑब्जेक्ट फ़ाइलों की सूची में शामिल किया जाना चाहिए जो प्रोग्राम के अंतिम निर्माण चरण में एक साथ जुड़े हुए हैं।

एमओसी लागू करने के लिए नियम बनाना

कुछ भी लेकिन सबसे सरल परीक्षण कार्यक्रमों के लिए, यह अनुशंसा की जाती है कि आप moc रनिंग को स्वचालित करें। अपने प्रोग्राम के मेकफाइल में कुछ नियम जोड़कर, जब आवश्यक हो तो रनिंग moc का ध्यान रख सकते हैं और moc आउटपुट को संभाल सकते हैं।

हम आपके qmake के निर्माण के लिए qmake जेनरेशन टूल का उपयोग करने की सलाह देते हैं। यह उपकरण एक मेकफाइल बनाता है जो सभी आवश्यक moc हैंडलिंग करता है।

यदि आप अपना मेकफाइल्स खुद बनाना चाहते हैं, तो यहां कुछ टिप्स दिए गए हैं कि कैसे मॉक हैंडलिंग को शामिल किया जाए।

शीर्ष लेख फ़ाइलों में Q_OBJECT वर्ग घोषणाओं के लिए, यहाँ एक उपयोगी नियम नियम है यदि आप केवल GNU मेक का उपयोग करते हैं:

moc_%.cpp: %.h
        moc $(DEFINES) $(INCPATH) $< -o [email protected]

यदि आप कुछ लिखना चाहते हैं, तो आप निम्न फॉर्म के अलग-अलग नियमों का उपयोग कर सकते हैं:

moc_foo.cpp: foo.h
        moc $(DEFINES) $(INCPATH) $< -o [email protected]

आपको अपने OBJECTS वैरिएबल में moc_foo.cpp को अपने SOURCES (अपने पसंदीदा नाम का विकल्प) चर और moc_foo.o या moc_foo.obj को जोड़ना याद रखना चाहिए।

दोनों उदाहरण मानते हैं कि $(DEFINES) और $(INCPATH) परिभाषित करने के लिए विस्तारित होते हैं और पथ विकल्प शामिल होते हैं जो C ++ कंपाइलर को पास किए जाते हैं। स्रोत फ़ाइलों को प्रीप्रोसेस करने के लिए moc द्वारा इनकी आवश्यकता होती है।

जब हम अपनी C ++ स्रोत फ़ाइलों को नाम देना पसंद करते हैं .cpp , आप चाहें तो किसी अन्य एक्सटेंशन, जैसे .C , .cc .CC , .cxx , और .c++ कर सकते हैं।

क्रियान्वयन ( .cpp ) फ़ाइलों में Q_OBJECT वर्ग घोषणाओं के लिए, हम इस तरह से एक नियम Q_OBJECT :

foo.o: foo.moc

foo.moc: foo.cpp
        moc $(DEFINES) $(INCPATH) -i $< -o [email protected]

यह गारंटी देता है कि foo.cpp संकलित करने से पहले foo.cpp । आप तब डाल सकते हैं

#include "foo.moc"

foo.cpp के अंत में, जहां उस फ़ाइल में घोषित सभी वर्ग पूरी तरह से ज्ञात हैं।

कमांड-लाइन विकल्प

यहाँ moc द्वारा समर्थित कमांड-लाइन विकल्प हैं:

विकल्प विवरण
-o<file> मानक आउटपुट के बजाय <file> आउटपुट लिखें।
-f[<file>] आउटपुट में #include स्टेटमेंट की पीढ़ी को फोर्स करें। यह हेडर फ़ाइलों के लिए डिफ़ॉल्ट है जिसका विस्तार H या H शुरू होता है। यह विकल्प उपयोगी है यदि आपके पास हेडर फाइलें हैं जो मानक नामकरण सम्मेलनों का पालन नहीं करते हैं। <file> भाग वैकल्पिक है।
-i आउटपुट में #include स्टेटमेंट जेनरेट न करें। यह एक या अधिक वर्ग घोषणाओं वाले C ++ फ़ाइल पर मॉक को चलाने के लिए उपयोग किया जा सकता है। फिर आपको .cpp फ़ाइल में मेटा-ऑब्जेक्ट कोड #include करना चाहिए।
-nw कोई चेतावनी उत्पन्न न करें। (सिफारिश नहीं की गई।)
-p<path> जनरेट किए गए #include स्टेटमेंट में फाइल के नाम पर moc प्रीपेंड <path>/ बनाता है।
-I<dir> हेडर फ़ाइलों के लिए शामिल पथ पर dir जोड़ें।
-E केवल प्रीप्रोसेस; मेटा-ऑब्जेक्ट कोड उत्पन्न न करें।
-D<macro>[=<def>] वैकल्पिक परिभाषा के साथ मैक्रो को परिभाषित करें।
-U<macro> अनिश्चितकालीन मैक्रो।
-M<key=value> अतिरिक्त मेटा डेटा प्लगइन्स में जोड़ें। यदि किसी वर्ग में Q_PLUGIN_METADATA निर्दिष्ट है, तो कुंजी-मूल्य जोड़ी को उसके मेटा डेटा में जोड़ा जाएगा। यह JSON ऑब्जेक्ट में समाप्त हो जाएगा जो रन टाइम (प्लगइन QPluginLoader से QPluginLoader ) के लिए हल हो जाता है। इस तर्क का उपयोग आमतौर पर निर्माण प्रणाली द्वारा हल की गई जानकारी के साथ स्थिर प्लगइन्स को टैग करने के लिए किया जाता है।
@<file> <file> से अतिरिक्त कमांड-लाइन विकल्प पढ़ें। फ़ाइल की प्रत्येक पंक्ति को एक ही विकल्प के रूप में माना जाता है। खाली लाइनों को नजरअंदाज कर दिया जाता है। ध्यान दें कि यह विकल्प विकल्प फ़ाइल के भीतर ही समर्थित नहीं है (यानी एक विकल्प फ़ाइल "दूसरी फ़ाइल को शामिल नहीं कर सकती")।
-h उपयोग और विकल्पों की सूची प्रदर्शित करें।
-v moc का संस्करण संख्या प्रदर्शित करें।
-Fdir मैक ओ एस। शीर्ष लेख फ़ाइलों के लिए खोज की जाने वाली निर्देशिकाओं की सूची के प्रमुख के लिए ढांचा निर्देशिका dir जोड़ें। इन निर्देशिकाओं को निर्दिष्ट निर्दिष्ट -I विकल्पों के साथ इंटरलेय किया गया है और उन्हें बाएं से दाएं क्रम में स्कैन किया गया है (gcc के लिए मैनपेज देखें)। आम तौर पर, उपयोग -F / लाइब्रेरी / फ्रेमवर्क /

आप स्पष्ट रूप से शीर्ष लेख फ़ाइल के कुछ हिस्सों को पार्स नहीं करने के लिए बता सकते हैं। moc प्रीप्रोसेसर प्रतीक Q_MOC_RUN को परिभाषित करता है। किसी भी कोड से घिरा हुआ

#ifndef Q_MOC_RUN
    ...
#endif

moc द्वारा छोड़ दिया जाता है।

निदान

moc आपको Q_OBJECT वर्ग की घोषणाओं में कई खतरनाक या अवैध निर्माणों के बारे में चेतावनी देगा।

यदि आपको अपने प्रोग्राम के अंतिम बिल्डिंग चरण में लिंकेज की त्रुटियां मिलती हैं, तो यह कहते हुए कि YourClass::className() अपरिभाषित है या YourClass नहीं है, कुछ गलत किया गया है। सबसे अधिक बार, आप मोक-जेनरेट किए गए C ++ कोड को संकलित करना या #include भूल गए हैं, या (पूर्व मामले में) लिंक कमांड में उस ऑब्जेक्ट फ़ाइल को शामिल करते हैं। यदि आप qmake उपयोग qmake , तो इसे अपने qmake को अपडेट करने के लिए पुन: निर्देशित करें। यह काम कर जाना चाहिए।

सीमाएं

moc सभी C ++ को हैंडल नहीं करता है। मुख्य समस्या यह है कि वर्ग टेम्पलेट में Q_OBJECT मैक्रो नहीं हो सकता है। यहाँ एक उदाहरण है:

class SomeTemplate<int> : public QFrame
{
    Q_OBJECT
    ...

signals:
    void mySignal(int);
};

निम्नलिखित निर्माण अवैध हैं। उन सभी के पास विकल्प हैं जो हमें लगता है कि आमतौर पर बेहतर होते हैं, इसलिए इन सीमाओं को हटाना हमारे लिए उच्च प्राथमिकता नहीं है।

मल्टीपल इनहेरिटेंस के लिए QObject की आवश्यकता होती है

यदि आप एक से अधिक वंशानुक्रम का उपयोग कर रहे हैं, तो moc यह मानता है कि पहली विरासत वाला वर्ग QObject उपवर्ग है। इसके अलावा, सुनिश्चित करें कि केवल पहली विरासत वाला वर्ग एक QObject

// correct
class SomeClass : public QObject, public OtherClass
{
    ...
};

QObject साथ वर्चुअल इनहेरिटेंस समर्थित नहीं है

फंक्शन पॉइंटर्स सिग्नल या स्लॉट पैरामीटर नहीं हो सकते

ज्यादातर मामलों में जहां आप फ़ंक्शन पॉइंटर्स को सिग्नल या स्लॉट मापदंडों के रूप में उपयोग करने पर विचार करेंगे, हमें लगता है कि विरासत एक बेहतर विकल्प है। यहाँ अवैध सिंटैक्स का एक उदाहरण दिया गया है:

class SomeClass : public QObject
{
    Q_OBJECT

public slots:
    void apply(void (*apply)(List *, void *), char *); // WRONG
};

आप इस तरह के प्रतिबंध के आसपास काम कर सकते हैं:

typedef void (*ApplyFunction)(List *, void *);

class SomeClass : public QObject
{
    Q_OBJECT

public slots:
    void apply(ApplyFunction, char *);
};

फंक्शन पॉइंटर को इनहेरिटेंस और वर्चुअल फ़ंक्शंस से बदलना कभी-कभी और भी बेहतर हो सकता है।

Enums और Typedefs सिग्नल और स्लॉट पैरामीटर के लिए पूरी तरह से योग्य होने चाहिए

इसके तर्कों के हस्ताक्षरों की जाँच करते समय, QObject::connect () डेटा प्रकारों की शाब्दिक तुलना करता है। इस प्रकार, Alignment और Alignment को दो अलग-अलग प्रकारों के रूप में माना जाता है। इस सीमा के आसपास काम करने के लिए, सिग्नल और स्लॉट की घोषणा करते समय और कनेक्शन स्थापित करते समय डेटा प्रकारों को पूरी तरह से योग्य बनाना सुनिश्चित करें। उदाहरण के लिए:

class MyClass : public QObject
{
    Q_OBJECT

    enum Error {
        ConnectionRefused,
        RemoteHostClosed,
        UnknownError
    };

signals:
    void stateChanged(MyClass::Error error);
};

नेस्टेड क्लासेस में सिग्नल या स्लॉट नहीं हो सकते हैं

यहाँ आपत्तिजनक निर्माण का एक उदाहरण है:

class A
{
public:
    class B
    {
        Q_OBJECT

    public slots:   // WRONG
        void b();
    };
};

सिग्नल / स्लॉट वापसी प्रकार संदर्भ नहीं हो सकते

सिग्नल और स्लॉट्स में वापसी के प्रकार हो सकते हैं, लेकिन संकेत या स्लॉट रिटर्निंग संदर्भों को रिटर्निंग शून्य माना जाएगा।

केवल सिग्नल और स्लॉट्स एक वर्ग के signals और slots अनुभागों में प्रकट हो सकते signals

moc शिकायत करेगा यदि आप सिग्नल और स्लॉट की तुलना में किसी वर्ग के signals या slots अनुभागों में अन्य निर्माणों को डालने का प्रयास करते हैं।

मेटा-ऑब्जेक्ट सिस्टम , सिग्नल और स्लॉट और Qt का प्रॉपर्टी सिस्टम भी देखें