.lib में C++ स्थिर वैरिएबल प्रारंभ नहीं होता है




visual-studio-2010 dll (2)

मेरे पास VS2010 में स्थैतिक पुस्तकालय (.lib) है और यह मेरे परीक्षण परियोजना से जोड़ रहा है।

लिब का एक कारखाना है जिसे मैं मैक्रो का प्रयोग करके बना देता हूं:

#define REGISTER_FACTORY(mType, my_class) \
class Factory##my_class : public CAbstractFactory\
{\
public:\
    Factory##my_class() : CAbstractFactory(mType){}\
    CBaseClass *Create()\
    { return new my_class(); }\
};\
static Factory##my_class StaticFactory##my_class;

क्या होने वाला है कि CAbstractFactory में नई कारखाने mtype द्वारा पंजीकृत हो mtype । लेकिन जब मैं कारखाने की जांच करता हूं तो कारखाना मौजूद नहीं है।

यह ठीक काम करता है जब मैं .lib के बजाय एक DLL का उपयोग करता हूं। मेरा अनुमान है कि लिंकर में स्थिर वैरिएबल शामिल नहीं है क्योंकि यह संदर्भित नहीं है या स्थिर वैरिएबल भी पुस्तकालय में शामिल नहीं था।

मैं कैसे लिंकर को मेरी .exe में स्थिर लाइब्रेरी से सभी ऑब्जेक्ट को शामिल करने के लिए बाध्य कर सकता हूं।

मैं इस तरह मैक्रो का उपयोग करता हूं:

// Register factory that can create CMyObject with ID=100
REGISTER_FACTORY(100, CMyObject);

class CMyObject
{
};

CAbstractFactory इस तरह दिखता है:

class CAbstractFactory {
    CAbstractFactory(int id) {
        CFactory::instance().add(id, this);
    }
}

तो फिर कुछ कोड में, मेरे मुख्य। Exe मैं का उपयोग करें:

CBaseClass *pObject = CFactory::instance().Create(100);

यह तब मेरी एक नई CMyObject । विचार यह है कि मेरे पास बहुत अलग प्रकार की वस्तु है और मेरे पास एक ऐसा डेटाबेस है जिसमें मुझे जिस प्रकार की ऑब्जेक्ट्स की ज़रूरत होती है, आईडी निर्दिष्ट हो। 100 सिर्फ एक उदाहरण है

तो वास्तव में, मैं सीधे लिबिल से कुछ भी संदर्भ नहीं करता हूं, लेकिन मैं अपने कारखाने का उपयोग करके वस्तुओं को बनाने में सक्षम होना चाहता हूं

सीएफएफ़ीटर क्लास एक साधारण वर्ग है जो सभी कैबरेक्टफैक्चर क्लास के एक रजिस्टर (मैप में) रखता है और सही फैक्टरी के लिए विधि बनाने के प्रतिनिधियों को देता है।

CFactory &CFactory::Instance()
{
    static CFactory instance;
    return instance;
}

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


मुझे एक समान समस्या थी और मुख्य ऐप प्रोजेक्ट की निर्भरता के रूप में लिब प्रोजेक्ट को सेट करके और फिर मुख्य परियोजना के लिए 'लिंक लाइब्रेरी निर्भरता' और 'लाइब्रेरी निर्भरता इनपुट का उपयोग' हाँ के लिए सेट करके हल किया।

अद्यतन करें:

हाल ही में मैंने पाया कि Visual Studio 2015 अब एक /WHOLEARCHIVE लिंकर ध्वज का समर्थन करता है मैं इसे लिंकर विकल्प के माध्यम से नहीं खोज सकता, लेकिन आप इसे एक अतिरिक्त कमांड लाइन विकल्प के रूप में जोड़ सकते हैं। यह जीसीसी ध्वज के समान काम करता है -whole-archive और आप इसे अपने लक्षित लिंकर झंडे में जोड़ते हैं (स्थैतिक -whole-archive लिए नहीं)।

उदाहरण के लिए, /WHOLEARCHIVE:lib_name निर्दिष्ट करें /WHOLEARCHIVE:lib_name को एक अतिरिक्त लिंकर कमांड लाइन विकल्प के रूप में निर्दिष्ट करें और इसमें उस लिब से सभी प्रतीकों को शामिल किया जाएगा। आप इसे एक से अधिक लिपि के रूप में भी कर सकते हैं।

यदि आप इस /WHOLEARCHIVE:lib_name उपयोग करते हैं तो आपको अब 'लिंक लाइब्रेरी निर्भरता' और 'लाइब्रेरी निर्भरता इनपुट का उपयोग' हाँ पर सेट की आवश्यकता है यह CMAKE के माध्यम से उत्पन्न समाधानों के लिए एकदम सही है एक संबंधित उत्तर यहां देखें: https://.com/a/42083877/1151329


static आंतरिक लिंकेज के साथ एक ऑब्जेक्ट को परिभाषित करता है -> अगर यह एक ही अनुवाद इकाई में आंतरिक रूप से उपयोग नहीं किया गया है, तो इसे ऑप्टिमाइज़ किया जा सकता है। ऑब्जेक्ट के लिए बाहरी लिंकिंग के लिए आपके तात्कालिकता से static निकालें - Factory##my_class StaticFactory##my_class;





static-members