17

के साथ संकलित किया गया है तो मैंने एक ऐसी प्रणाली बनाई है जो वैश्विक उदाहरण के निर्माता के आधार पर स्वचालित रूप से फ़ंक्शन ऑब्जेक्ट्स (फ़ैक्टर) को मानचित्र में पंजीकृत करता है।सी ++ ग्लोबल वैरिएबल प्रारंभिक पुस्तकालयों के माध्यम से लिंक नहीं किया गया है, लेकिन जब स्रोत

प्रत्येक सीपीपी फ़ाइल में जो मिक्सर को परिभाषित करता है, रजिस्ट्रार क्लास इंस्टेंस का ग्लोबल इंस्टेंस है जो मल्टीक्टर को सिंगलटन std::map<int, std::function<...> > ऑब्जेक्ट में पंजीकृत करने के लिए है।

template 
< 
    typename map_type, 
    typename handler_type 
> 
struct registrar 
{ 
    registrar 
     (
      map_type& map_object, 
      boost::uint16_t cmd_code, 
      const handler_type& handler 
     ) 
     { 
      map_object.insert(std::pair<boost::uint16_t, handler_type>(cmd_code, handler)); 
     } 
}; 
प्रत्येक .cpp फ़ाइल में

:

यह रजिस्ट्रार वर्ग की परिभाषा है। वैश्विक उदाहरण इस तरह परिभाषित किया गया है: अगर मैं एक साथ main.cpp के साथ सभी सीपीपी संकलन

namespace one_way 
{ 
    static registrar <in_out_map_type, handler> 
     post_receiver(in_out_map_type::instance(), command, handlers()); 
} 

सभी ठीक काम करता है। लेकिन अगर मैं एक सीपीपी फ़ाइल को स्थिर पुस्तकालय में संकलित करता हूं और इसे main.cpp से लिंक करता हूं, तो पंजीकरण काम नहीं करता है।

मैंने विंडोज & और उबंटू 11.10 दोनों पर वीसी 10 और जीसीसी 4.61 के साथ परीक्षण किया। दोनों असफल हो जाते हैं।

मुझे a thread with the same problem मिला लेकिन ओपी ने यह नहीं कहा कि उसने इसे हल किया है या नहीं।

क्या मुझे कुछ याद आ रही है?


संपादित


टिप्पणियों सहित सभी प्रतिक्रियाओं के लिए धन्यवाद।

प्रत्येक प्रतिक्रिया ने वास्तव में मुझे और अधिक सोचने और इस विधि में गहरी जांच करने में मदद की। सभी अध्ययन और परीक्षणों के बाद, मैं अंत में ऊपर द्विआधारी सीमाओं भर में आत्म पंजीकरण के लिए वैश्विक/स्थिर चर पर निर्भर का विचार है, दिया नहीं पोर्टेबल गारंटी करने के लिए यह काम करेंगे तरीका नहीं है।

मेरा अंतिम तरीका पंजीकरण को एक बाइनरी में रखना है।

+0

आप यह नहीं दिखाते कि आप पंजीकृत कार्यों के लिए रजिस्ट्रार को कैसे कॉल कर रहे हैं। साथ ही, 'ग्लोबल इंस्टेंस' ('हैंडलर()' के बजाय 'हैंडलर()' में एक टाइपो है? जब तक कि मुझे कुछ याद नहीं आ रहा है, जो एक फ़ंक्शन को परिभाषित करता है, न कि वैश्विक चर। तो, ऐसा लगता है, मुझे लगता है कि तस्वीर से कई कनेक्टिंग डॉट्स गायब हैं ... –

+4

फ़ंक्शन पंजीकृत करने के लिए स्थिर प्रारंभिकरण पर निर्भर होने से शायद लंबे समय तक थोड़ा सा त्रुटि हो सकती है। क्या आपने अभी स्पष्ट पंजीकरण किया है? –

+0

जीसीसी के लिए, एक नज़र डालें, -ब्लूएल, - संपूर्ण संग्रह मदद करता है। –

उत्तर

-1

मेरा मानना ​​है कि लाइब्रेरी से आपकी ऑब्जेक्ट फ़ाइल लिंक नहीं हो रही है। देखें कि माइक्रोसॉफ्ट कैसे घुमावदार प्रतीक को नियंत्रित करता है (खोज केस असंवेदनशील है, मुझे इस मामले पर कोई एमएसवीसी नहीं है)।

एक बार जब आप जानते हैं कि वे कैसे एन्क्रिप्टेड हैंडल करते हैं, तो अपने ग्लोबल वैरिएबल के साथ वही काम करें जो इसे जोड़ने के लिए मजबूर करता है।

अगर मुझे उत्तर मिल जाए तो अपडेट हो जाएगा।

कुछ हद तक मजबूर आदेशों को जोड़ने और प्रारंभ करने के लिए मजबूर करने के लिए कुछ संभावनाएं हैं।

एक जीसीसी उत्तर के लिए here देखें।

MSVC10 के लिए here देखें।

+0

लिंक के लिए धन्यवाद। कृपया ओपी में मेरा संपादन देखें। –

0

सुनिश्चित नहीं हैं कि अगर यह कोई मदद या नहीं होगा, लेकिन मैं एक सवाल है कि बहुत समान लगता पूछा:

C++ runtime knowledge of classes

हो सकता है कि इस पर एक नज़र लेने लायक?

+0

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

+0

पंजीकरण वास्तव में एक .cc फ़ाइल में किया जाता है ..., जब तक ऐप पंजीकृत सामग्री बनाने के लिए कारखाने का उपयोग करता है, पंजीकरण स्वचालित रूप से हटाया नहीं जाएगा। मैंने स्वयं एक ही चीज का इस्तेमाल एए में किया है और बिना किसी समस्या के संकलित और इसके खिलाफ जुड़ा हुआ है। –

+0

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

7

एंड्रॉइड एनडीके काम के लिए संक्षिप्त उत्तर, इस समस्या से प्रभावित किसी भी स्थिर libs को LOCAL_WHOLE_STATIC_LIBRARIES चर में जोड़ा जाना चाहिए - फिर उन्हें -Wl,--whole-archive ध्वज का उपयोग करके संदर्भित किया जाएगा और स्ट्रिपिंग के अधीन नहीं होंगे। MSVC के लिए

लंबे समय तक जवाब:

एक अनुवाद इकाई में स्थैतिक चर अनुवाद इकाई में किसी भी नियमित रूप से कोड कार्यान्वित होने से पहले प्रारंभ कर रहे हैं। अभ्यास में प्रारंभ होता है जब निष्पादन योग्य या गतिशील लाइब्रेरी लोड होती है। जब आपका \ c मुख्य() कहा जाता है, या LoadLibrary()/dlopen() पर आपका कॉल पूरा हो जाता है, तो किसी स्थिर चर को प्रारंभ किया जाएगा।

समस्या, के रूप में MSDN द्वारा वर्णित:

कंस्ट्रक्टर्स और असाइनमेंट वैश्विक समारोह या घोषणा में स्थिर तरीके से करते हैं एक संदर्भ नहीं बना सकते हैं और/ऑप्ट नहीं रोका जाएगा: REF उन्मूलन। ऐसे कोड से साइड इफेक्ट्स पर निर्भर नहीं किया जाना चाहिए जब डेटा के कोई अन्य संदर्भ मौजूद न हों।

यह एक फ़ाइल में अनेक अनुवाद इकाइयों से वस्तु कोड डालने की सुविधाजनक हो सकता है, एक स्थिर पुस्तकालय पारंपरिक एक \ ग उदारीकरण या \ ग ए प्रत्यय के साथ नाम दिया है। एमएसवीसी लिंकर स्थिर पुस्तकालयों पर निर्भरता विश्लेषण करता है और इसमें शामिल कोड द्वारा संदर्भित कोड शामिल नहीं होगा।

घोषित करने और के पंजीकरण एक कारखाने वस्तु इस परिस्थिति में असफल हो सकता है पैदा करने के लिए एक स्थिर चर का उपयोग कर के आम पैटर्न - MSVC लिंकर के रूप में स्थिर नहीं पहुंचा जा सकता जा रहा है समझे और परिणाम से यह स्ट्रिप्स।

समाधान

एक उपयोगी Google खोज

: http://www.google.com/search?q=msvc+factory+static+library

एक समाधान सहित इकाई पर /OPT:NOREF लिंकर ध्वज सेट करने के लिए है। हालांकि, यह सब कुछ या कुछ भी सेटिंग नहीं है, और इसकी आवश्यकता होगी कि सभी शामिल पुस्तकालय पूरी तरह से लिंक करने योग्य हों।

यदि स्थिर समेत फ़ाइल में कुछ संदर्भित है (0 अप्रत्यक्ष रूप से) इकाई सहित, तो भाषा नियमों के अनुसार स्थिर स्वयं को संरक्षित किया जाना चाहिए।

सबसे बुनियादी दृष्टिकोण फ़ाइल में एक डमी फ़ंक्शन डालना है, और संदर्भ से कहीं भी पहुंचने योग्य माना जाता है।

एक और तरीका समस्या फ़ाइल में किसी इकाई को संदर्भित करने के लिए /INCLUDE लिंकर ध्वज का उपयोग करना है। DummyForLinkProblem नामित एक इकाई मान लिया जाये कि, इस सहित इकाई के स्रोत में किया जा सकता:

#pragma comment(linker, "/include:DummyForLinkProblem") 

ZooLib's Solution

ZooLib इकाई इस समस्या से प्रभावित ZFile_Win.cpp, ZGRgnRep_HRGN में होते हैं। सीपीपी, ZNet_Internet_WinSock.cpp, ZStreamRWCon_SSL_Win.cpp, ZTextCoder_Win.cpp और ZUnicode_Normalize_Win.cpp।

हम संबंधित हेडर फ़ाइलों में #include ZCompat_MSVCStaticLib.h, और प्रत्येक ZMACRO_MSVCStaticLib_Reference(ModifiedFileName) में डाल दिया। सीपीपी फाइलों में हमने ZMACRO_MSVCStaticLib_cpp(ModifiedFileName) डाला। ModifiedFileName आम तौर पर अग्रणी जेड और फ़ाइल एक्सटेंशन के साथ फ़ाइल नाम हटा दिया गया है, के समान शैली ZCONFIG_API_XXX मैक्रोज़ में उपयोग की जाती है।

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