2012-12-29 10 views
14

मैं पहले उल्लेख करना चाहता हूं कि निम्नलिखित क्यूटी 5.0.0 बीटा 1 (शायद बीटा 2 और आरसी भी, पता नहीं) तक ठीक काम करता है, लेकिन क्यूटी में विफल रहता है 5.0.0 अंतिम रिलीज संस्करण। मैं केवल क्यूटी 5.0.0 अंतिम रिलीज संस्करण में देखे गए परिणामों का उल्लेख करना चाहता हूं। तो शायद यह Qt5 में हाल के परिवर्तनों के साथ कुछ करने के लिए है।सी ++ का उपयोग करें - क्यूएमएल में स्लॉट जो नामस्थान में टाइप करता है

सी ++ पक्ष पर मेरे पास नामस्थान में कक्षाओं (क्यूओब्जेक्ट-व्युत्पन्न) का एक सेट है (जिसे वैकल्पिक रूप से कंपाइलर झंडे से ट्रिगर किया जाता है; कक्षाएं अलग पुस्तकालय में होती हैं और लाइब्रेरी एक विकल्प के रूप में नामस्थान का उपयोग छोड़ देती है पुस्तकालय का उपयोगकर्ता)। एक वर्ग है, यहाँ Game, इस (अंश) दिखाई देंगे:

OAE_BEGIN_NAMESPACE 

// forward-declarations: 
class Player; // Player is just another class in the same library 

class Game : public QObject 
{ 
    Q_OBJECT 

public: 
    explicit Game(...); 

public slots: 
    Player *player() const; // <-- the quesion is about such slots 
}; 

OAE_END_NAMESPACE 

मैक्रो OAE_BEGIN/END_NAMESPACE के लिए या तो namespace OAE_NAMESPACE { ... } या कुछ भी नहीं का विस्तार, उसी तरह क्यूटी <qglobal.h> में यह करता है में, बस "क्यू" की जगह "OAE" मैक्रो नाम के साथ:

#ifndef OAE_NAMESPACE 

# define OAE_PREPEND_NAMESPACE(name) ::name 
# define OAE_USE_NAMESPACE 
# define OAE_BEGIN_NAMESPACE 
# define OAE_END_NAMESPACE 
# define OAE_BEGIN_INCLUDE_NAMESPACE 
# define OAE_END_INCLUDE_NAMESPACE 
# define OAE_BEGIN_MOC_NAMESPACE 
# define OAE_END_MOC_NAMESPACE 
# define OAE_FORWARD_DECLARE_CLASS(name) class name; 
# define OAE_FORWARD_DECLARE_STRUCT(name) struct name; 
# define OAE_MANGLE_NAMESPACE(name) name 

#else /* user namespace */ 

# define OAE_PREPEND_NAMESPACE(name) ::OAE_NAMESPACE::name 
# define OAE_USE_NAMESPACE using namespace ::OAE_NAMESPACE; 
# define OAE_BEGIN_NAMESPACE namespace OAE_NAMESPACE { 
# define OAE_END_NAMESPACE } 
# define OAE_BEGIN_INCLUDE_NAMESPACE } 
# define OAE_END_INCLUDE_NAMESPACE namespace OAE_NAMESPACE { 
# define OAE_BEGIN_MOC_NAMESPACE OAE_USE_NAMESPACE 
# define OAE_END_MOC_NAMESPACE 
# define OAE_FORWARD_DECLARE_CLASS(name) \ 
    OAE_BEGIN_NAMESPACE class name; OAE_END_NAMESPACE \ 
    using OAE_PREPEND_NAMESPACE(name); 

# define OAE_FORWARD_DECLARE_STRUCT(name) \ 
    OAE_BEGIN_NAMESPACE struct name; OAE_END_NAMESPACE \ 
    using OAE_PREPEND_NAMESPACE(name); 

# define OAE_MANGLE_NAMESPACE0(x) x 
# define OAE_MANGLE_NAMESPACE1(a, b) a##_##b 
# define OAE_MANGLE_NAMESPACE2(a, b) OAE_MANGLE_NAMESPACE1(a,b) 
# define OAE_MANGLE_NAMESPACE(name) OAE_MANGLE_NAMESPACE2(\ 
     OAE_MANGLE_NAMESPACE0(name), OAE_MANGLE_NAMESPACE0(OAE_NAMESPACE)) 

namespace OAE_NAMESPACE {} 

# ifndef OAE_BOOTSTRAPPED 
# ifndef OAE_NO_USING_NAMESPACE 
    /* 
    This expands to a "using OAE_NAMESPACE" also in _header files_. 
    It is the only way the feature can be used without too much 
    pain, but if people _really_ do not want it they can add 
    DEFINES += OAE_NO_USING_NAMESPACE to their .pro files. 
    */ 
    OAE_USE_NAMESPACE 
# endif 
# endif 

#endif /* user namespace */ 

निम्नलिखित में, जब कह मूल्य oae साथ इस मामले में, मेरा मतलब है मैं मैक्रो OAE_NAMESPACE घोषणा की, "नाम स्थान को सक्षम करने"।

दूसरों के बीच में, मैं इस कक्षा के उदाहरणों और Player कक्षा तक पहुंचता हूं जैसा कि player() द्वारा मेरे आवेदन के उपयोगकर्ता इंटरफ़ेस के लिए QML के भीतर से लौटाया गया है। इस के लिए, मैं वर्गों रजिस्टर इस प्रकार है:

qmlRegisterType<Game>(); 
qmlRegisterType<Player>(); 

मैं QML एक Game का एक उदाहरण के लिए सूचक दृश्यपटल प्रदान करते हैं theGame QML के भीतर बुलाया:

view.engine()->rootContext()->setContextProperty("theGame", 
     QVariant::fromValue<Game*>(game)); 

QML के भीतर, मैं के रूप में उपयोग हमेशा की तरह।

Rectangle { 
    width: 100; height: 100 
    Component.onCompleted: console.log(theGame.player()) 
} 

मैं मिल निम्नलिखित परिणाम, कि क्या मैं सेट के आधार पर एक OAE_NAMESPACE या नहीं (वैसे: मैं एक ही सेटिंग दोनों पुस्तकालय और के लिए उपयोग एक छोटा सा उदाहरण player() का एक सूचक पता प्रिंट चाहिए आवेदन इसे का उपयोग):

  • जब नाम स्थान अक्षम करने, सब कुछ उम्मीद के रूप में काम करता है और QML मुझे सूचक प्रिंट:

    Player(0x10b4ae0) 
    
  • जब नाम स्थान को सक्षम करने के लिए (और सी ++ लाइब्रेरी का उपयोग कर कोड में यह using, तो मैं बिल्कुल कोड में परिवर्तन नहीं करते), QML करने में विफल रहता Game::player() की वापसी प्रकार को समझने:

    Error: Unknown method return type: Player* 
    
  • जब oae::Player* को वापसी प्रकार Game::player() की बदल रहा है, सब कुछ फिर से ठीक काम करता है:

    oae::Player(0x10b4ae0) 
    

मेरा निष्कर्ष है कि अब तक moc नाम स्थान मैं कक्षा के आसपास डाल पर विचार नहीं करता है। मेरा पहला अनुमान था: अरे, moc पता नहीं है कि मैं जब g++ बुला नाम स्थान को परिभाषित है, जो है जो मैं .pro फ़ाइल में कार्य करें:

DEFINES += OAE_NAMESPACE=oae 

हालांकि, जब OAE_NAMESPACE::Player* में लौटने प्रकार बदल कर, यह अभी भी काम करता है, इसलिए OAE_NAMESPACE मैक्रो के बारे में पता है, लेकिन यह या तो OAE_BEGIN/END_NAMESPACE मैक्रोज़ का विस्तार नहीं करता है या यह अब नामस्थानों का विश्लेषण नहीं करता है।

  • जब नाम स्थान अक्षम और वापसी प्रकार Player* का उपयोग कर:

    mocPlayer * Game::player() const जो विधि की वापसी प्रकार containes निम्नलिखित "stringdata" पैदा करता है

    "player\0Player*\0" 
    
  • जब नामस्थान सक्षम करना और वापसी प्रकारका उपयोग करना 0:

    "player\0Player*\0" 
    
  • जब नाम स्थान सक्षम करने और वापसी प्रकार OAE_NAMESPACE::Player* का उपयोग कर के रूप में नाम स्थान है, तो साथ QMetaObject::className() द्वारा दिया

    "player\0oae::Player*\0" 
    

दूसरी ओर, moc पहले जोड़ता वर्ग के नाम सक्षम होना चाहिए।

मेरा निष्कर्ष है कि मैं अब ClassName के बजाय OAE_NAMESPACE::ClassName लेखन जब भी इन प्रकार का उपयोग कर QObject मेटा तरीकों के हस्ताक्षर में करके इसे ठीक कर सकता है। (ठीक है, बेहतर मैक्रो OAE_PREPEND_NAMESPACE है)। चूंकि यह कोड में भयानक लगेगा, और मेरे लिए यह भी गलत लगता है क्योंकि विधि पहले से ही नामस्थान, में एक बेहतर समाधान है?

अब वहाँ भी OAE_BEGIN/END_MOC_NAMESPACE (अनुरूप QT_BEGIN/END_MOC_NAMESPACE के लिए), तो शायद मैं उन कहीं भी की जरूरत है? मुझे नहीं पता कि वे क्यूटी में कहां/कैसे उपयोग किए जाते हैं, इसलिए मुझे उनकी लाइब्रेरी में तदनुसार उनका उपयोग करना चाहिए, क्योंकि मैं क्यूटी के समान वैकल्पिक नामस्थान सुविधा का उपयोग करना चाहता हूं।

+0

मैं किस कोड मॉक का उत्पादन करता हूं (उदाहरण के लिए स्लॉट का हस्ताक्षर कैसे पार्स किया गया था) पर कुछ जानकारी जोड़ देगा। – leemes

+1

qmlRegisterType <> नामस्थान-योग्य टाइपनाम के साथ कुछ भी बदलता है? – mlvljr

+0

@mlvjr आपके संकेत के लिए धन्यवाद, लेकिन मैंने पहले ही यह कोशिश की है। असल में, यह कुछ भी नहीं बदला जाना चाहिए, क्योंकि यह एक सी ++ प्रकार निर्दिष्ट है लेकिन यह है कि 'moc' हेडर फ़ाइल को कैसे पार करता है। यह पता नहीं लगाता है कि नेमस्पेस के भीतर 'प्लेयर' वास्तव में नामस्थान के बाहर उपयोग किए जाने पर कक्षा 'ओए :: प्लेयर' को संदर्भित करता है। इसके अलावा मेरा मानना ​​है कि यह व्यवहार क्यूटी 5.0.0 अल्फा और बीटा 1 में अलग था। – leemes

उत्तर

8

क्या यह वास्तव में 5.0.0a में काम किया था?

मैंने क्यूटी 5.0.0 स्रोत कोड के माध्यम से ब्राउज़ किया और देखा कि विधियों को पार्स किया गया है, विशेष रूप से रिटर्न प्रकार (fyi, 5.0.0 \ qtbase \ src \ tools \ moc \ moc.cpp: L160) और कोई नामस्थान नहीं है जांचें (न तो तर्कों पर, player(Player* p) या तो काम नहीं करेगा)। जबकि, यह वर्ग डीईएफ़ के लिए किया जाता है (5.0.0 \ qtbase \ src \ उपकरण \ MOC \ moc.cpp: L620 & L635)

मुझे लगता है कि "हम" यह एक बग (या एक निरीक्षण)

कॉल कर सकते हैं
+0

आपके प्रयास के लिए धन्यवाद। मैं कल इसे दोबारा जांचूंगा। बेशक गलती मेरी तरफ हो सकती है, मैं इस संभावना को बाहर नहीं करना चाहता;) – leemes

+0

ठीक है, ऐसा लगता है कि क्यूटी 5.0.0 बीटा 1 में भी काम नहीं है। मैंने बस इसे पुनः प्रयास किया। अजीब बात है कि मुझे याद आया कि यह काम किया। इस सामग्री को मोक कोड में ढूंढने और अपने बक्षीस बिंदुओं के लिए बधाई देने में अपना समय लगाने के लिए धन्यवाद! – leemes

संबंधित मुद्दे