2009-09-08 13 views
9

मेरे पास अगली स्थिति है: मुझे स्टैंडअलोन स्थिर लाइब्रेरी में विजेट बनाना होगा, जिसे अंतिम एप्लिकेशन (विज़ुअल सी ++ 9.0, क्यूटी 4.5) से जोड़ा जाएगा। इस स्थिर विजेट लाइब्रेरी में कुछ संसाधन (आइकन) हैं, और इसमें कई .cpp फ़ाइलें शामिल हैं (प्रत्येक में स्टैंडअलोन विजेट होता है)। जहां तक ​​मुझे पता है, मुझे क्यूटी संसाधन प्रणाली शुरू करनी होगी, अगर मैं स्थिर पुस्तकालय में उन्हें (संसाधन) का उपयोग करता हूं, तो "Q_INIT_RESOURCE (resource_file_name)" पर कॉल करें। मैं अगले कोड के साथ इस हल (स्थिर पुस्तकालय में हर .cpp फ़ाइल में):स्थैतिक पुस्तकालय में एम्बेडेड क्यूटी संसाधनों को शुरू करना

 

#include <QAbstractButton> 

namespace { 
struct StaticLibInitializer 
{ 
    StaticLibInitializer() 
    { 
     Q_INIT_RESOURCE(qtwidgets_custom_resources); 
    } 
}; 
StaticLibInitializer staticLibInitializer; 
} 

// ... widget code .... 
 

मेरा पहला दृष्टिकोण के बजाय, मैं अलग init.cpp फ़ाइल स्थिर पुस्तकालय परियोजना में प्रवर्तन कोड के साथ बनाया है (आरंभीकरण शामिल होने से बचाया प्रत्येक .cpp फ़ाइल में कोड), लेकिन यह काम नहीं किया।

यह क्यों काम नहीं किया?

क्या StaticLibInitializer के साथ यह दृष्टिकोण विभिन्न कंपाइलरों और प्लेटफार्मों के बीच सुरक्षित और पोर्टेबल है?

उत्तर

10

यह काम नहीं किया क्योंकि आप static initialization order fiasco द्वारा हिट करने में कामयाब रहे।

आप अपने कोड को स्थानांतरित नहीं कर सकते हैं जो स्थैतिक वस्तुओं को अनुवाद इकाई को आउटस्टाइज़ करता है (आप इसे स्रोत फ़ाइल के रूप में पढ़ सकते हैं) जहां इन स्थिर वस्तुओं का उपयोग किया जाता है। जिस तरह से आपने इसे नहीं किया। यदि आप इस योजना का उपयोग करना चाहते हैं, तो आप इन स्थिर वस्तुओं को आरंभ करने के लिए उपयोग कर रहे हैं, केवल अपने init.hpp शीर्षलेख पर घोषणाओं को स्थानांतरित करने के लिए, लेकिन स्थिर वस्तुओं का उपयोग करने वाली प्रत्येक फ़ाइल में StaticLibInitializer staticLibInitializer; को छोड़ दें।
सलाह से ऊपर प्रत्येक विजेट केवल अपने संसाधनों का उपयोग करता है मानता है। यदि आपके पास ऐसी स्थिति है जिसमें एक विजेट के संसाधनों का उपयोग किसी अन्य विजेट द्वारा किया जाता है, तो आप स्थिर प्रारंभिक क्रम में फिर से चलते हैं। आप इस

StaticLibInitializer 
{ 
    void initialize() 
    { 
     static Q_INIT_RESOURCE(qtwidgets_custom_resources); 
    } 

    StaticLibInitializer() 
    { 
     initialize(); 
    } 
} 

की तरह कोड का उपयोग केवल एक बार दिए गए संसाधन प्रारंभ हो जाएगा StaticLibInitializer के बारे में सुनिश्चित गुणा instantiations बनाने के लिए और उसके बाद हर संसाधन आप दिए गए अनुवाद इकाई में उपयोग करने के लिए जा रहे हैं के लिए StaticLibInitializer का दृष्टांत से इस स्थिति का प्रबंधन कर सकते हैं।

+0

मेरी वर्तमान स्थिति में मेरे पास तीन .cpp फ़ाइलें हैं (उनमें से प्रत्येक अपने स्वयं के विजेट लागू करता है, उनमें से दो .qrc फ़ाइल से संसाधनों का उपयोग करते हैं), लेकिन प्रारंभिक कोड, जिसे मैंने मूल प्रश्न में दिया था, केवल उनमें से एक और सभी कार्यों में ठीक (100%, 50/50 नहीं)। तो मैं समझ नहीं पा रहा हूं, क्यों जब मैंने अलग-अलग init में प्रारंभिक कोड रखा।सीपीपी फ़ाइल मैं अपने संसाधनों का उपयोग नहीं कर सकता, लेकिन जब यह कोड विजेट की .cpp फ़ाइल में से किसी एक में ठीक काम करता है ... – cybevnm

+0

इससे कोई फर्क नहीं पड़ता कि यह ठीक काम करता है ** अब ** :) यह केवल दुर्घटना से काम करता है। यह उस क्षण को काम करना बंद कर सकता है जब आप किसी अन्य कंपाइलर या उसी कंपाइलर के किसी अन्य संस्करण का उपयोग शुरू करते हैं। यह ** निहित बहेवियर ** है। अब यह काम करने का कारण यह है कि जब आपके पास विजेट के फाइल कंपाइलर में से एक में प्रारंभिक कोड होता है ** ** होता है ** पहले अपने संसाधनों को आरंभ करने के लिए। शुद्ध भाग्य, और कुछ नहीं। यदि आप अपने प्रोग्राम को 0% एक धूप दिन काम नहीं करना चाहते हैं तो * स्थिर प्रारंभिक आदेश fiasco * से बचने के लिए निर्देशों का पालन करें। –

+0

संकलन चरण में संकलक द्वारा परिभाषित स्थैतिक प्रारंभिक क्रम है, या प्रोग्राम पुनरारंभ (बिना पुनर्मूल्यांकन के) के बीच भिन्न हो सकता है? – cybevnm

6

Q_INIT_RESOURCE मैक्रो नामस्थान में उपयोग नहीं किया जा सकता है।

मुझे क्यूटी मैनुअल से उद्धरण दें: "नोट: इस मैक्रो को नामस्थान में उपयोग नहीं किया जा सकता है। इसे मुख्य()" से जाना जाना चाहिए।

inline void initMyResource() { Q_INIT_RESOURCE(myapp); } 

    namespace MyNamespace 
    { 
    ... 

    void myFunction() 
    { 
     initMyResource(); 
    } 
    } 

कृपया अपने आप को क्यों और कैसे वास्तव में यह विफल रहता है या असफल नहीं पड़ता कि आप एक अनिर्दिष्ट तरह से इसका इस्तेमाल देखो: और यहां तक ​​कि यह आपको एक उदाहरण है, तो यह संभव नहीं है कि यह कैसे सही करने के लिए, देता है। प्रासंगिक कोड QtCore में है।

+0

लेकिन पहले दृष्टिकोण में (जब मैं स्थैतिक पुस्तकालय की प्रत्येक .cpp फ़ाइल में कोड शामिल करता हूं) यह काम करता है (अज्ञात नामस्थान के साथ भी)। – cybevnm

+0

उपरोक्त 'इनलाइन' का उपयोग करके आपको कुछ भी नहीं खरीदता है क्योंकि आपके पास कोई गारंटी नहीं है कि इसे एक कंपाइलर द्वारा सम्मानित किया जाएगा। * नहीं * इस कीवर्ड का सम्मान सी ++ मानक के अनुसार है। तो यदि यह * समाधान * धारणा इनलाइन फ़ंक्शन पर आधारित है, तो इसे रेखांकित किया जाएगा। –

+1

'इनलाइन' फ़ंक्शंस में थोड़ा अलग अर्थशास्त्र है, खासकर जब यह ओडीआर की बात आती है। ध्यान में रखते हुए हम सभी प्लेटफार्मों पर 'Q_INIT_RESOURCE' के मैक्रो विस्तार को नहीं जानते हैं, यह जरूरी है कि यह आवश्यक है या नहीं। इसे वहां रखना उचित है। – MSalters

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