2009-05-17 20 views
7

मैंने स्थैतिक पुस्तकालय के हिस्से के रूप में एक बहुत ही बुनियादी "प्लग-इन सिस्टम" लागू किया है। प्रत्येक "प्लग-इन" एक विशिष्ट छवि प्रारूप के लिए समर्थन लागू करता है, उदा। जीआईएफ, जेपीईजी, आदि .. इसके अलावा, मेरे पास सिंगलटन (PluginManager नामक एक वर्ग) है जो सभी उपलब्ध प्लग-इन की एक सूची रखता है।स्टेटिक लाइब्रेरी में ऑब्जेक्ट पंजीकरण

मुश्किल हिस्सा यह है कि मैं प्रोजेक्ट फ़ाइल से अपनी स्रोत फ़ाइलों को जोड़कर या हटाकर प्लग-इन को अक्षम/सक्षम करना चाहता हूं। इसे प्राप्त करने के लिए, प्रत्येक प्लग-इन एक वैश्विक चर (विभिन्न नामों के साथ) बनाता है और उस वर्ग के निर्माता में प्लग-इन को PluginManager पर पंजीकृत करता है।

कुछ JPEG प्रारूप के लिए इस तरह ...

struct JPEGPlugin 
{ 
    // constructor will register plugin 
    JPEGPlugin() 
    { 
    PluginManager::Singleton().RegisterPlugin(this); 
    } 

    // plenty of other code 
    ... 
}; 

JPEGPlugin jpeg_instance; // instantiate in global scope 

हालांकि, जबकि इस सिद्धांत में पूरी तरह से काम करता है, यह विफल रहता है, जब अन्य कोड को यह स्थिर पुस्तकालय को जोड़ने एक निष्पादन योग्य बनाने के लिए। जब तक यह निष्पादन योग्य प्लगइन ग्लोबल्स (जैसे jpeg_instance) तक नहीं पहुंचता है, तो लिंकर को कनेक्शन नहीं दिखाई देता है (वह पूरी तरह से निर्माता के दुष्प्रभावों को अनदेखा करता है) और अंतिम निष्पादन योग्य में कोड शामिल नहीं करता है। दूसरे शब्दों में, जेपीईजी प्लग-इन अंतिम ऐप में उपलब्ध नहीं है।

मैं पिछले कुछ वर्षों में समस्याओं में भाग गया, और मैंने हमेशा समाधान के लिए नेट की खोज की। हर बार, मुझे बस ऐसे पृष्ठ मिलते हैं जो मूल रूप से कहते हैं कि यह एक ज्ञात समस्या है और मुझे इसके साथ रहना है।

लेकिन शायद एसओ पर कोई जानता है कि यह कैसे काम कर रहा है?

उत्तर

2

मैं इस करता है, तो जिस तरह से आप इस समस्या का समाधान के लिए एक समाधान पता नहीं है, लेकिन हम एक वस्तु कारखाने के स्थिर पंजीकरण के साथ एक समान समस्या थी और दृश्य स्टूडियो में हम हल यह __declspec (dllexport) से जुड़ी कक्षाओं की घोषणा करके यह आवश्यक था, भले ही पुस्तकालय शामिल थे, डीएलएस नहीं थे। लेकिन इसके बिना लिंकर संदर्भित कक्षाओं को छोड़ देगा।

रजिस्ट्री समाधान हमने थोड़ा अलग काम किया और इसमें आवंटित ऑब्जेक्ट्स शामिल नहीं थे। मैंने सीपीपी-यूनिट से कुछ हिस्सों को उठाया, यह भी है जहां मैंने __declspec दृष्टिकोण iirc की खोज की।

[संपादित करें] हमें कोड के कुछ हिस्सों से पंजीकृत कक्षा की घोषणा #include भी थी।

+0

ठीक है, मैंने अभी आपका संपादन देखा - यह एक बड़ा मुद्दा है! :) –

2

चूंकि यह एक स्थिर मुक्ति है, तो आप प्रबंधक को प्लगइन पंजीकृत कर सकते हैं (प्लगइन को स्वयं पंजीकृत करने के बजाय)।

 
#include "JpegPlugin.h" 

void PluginManager::RegisterPlugins() 
{ 
#idef JPEG_PLUGIN 
    RegisterPlugin(&jpeg_instance); 
#endif 
} 

JpegPlugin.h जरूरी की परिभाषा में शामिल करने की जरूरत नहीं है: हेडर फाइल कुछ preproc प्रतीक (यानी JPEG_PLUGIN) ही नियंत्रित करता है या नहीं, प्रबंधक हैडर के शामिल किए जाने के आधार पर प्लगइन पंजीकृत करता है परिभाषित कर सकते हैं जेपीजीप्लगिन। यह कुछ इस तरह हो सकता है:

 
#ifndef JPEG_PLUGIN_HEADER 
#define JPEG_PLUGIN_HEADER 

#if 0 // change this to 1 to use the plugin 
#define JPEG_PLUGIN 
#include "Jpeg_PluginCls.h" 
#endif 

#endif 
+1

उत्तर के लिए धन्यवाद। हालांकि, जैसा कि आप स्वयं से इंगित करते हैं, यह प्रबंधक से प्लग-इन पर निर्भरता प्रस्तुत करता है - कुछ मैं टालना चाहता हूं! कारण यह है कि अन्य लोगों को प्रबंधक वर्ग को बदलने की आवश्यकता के बिना प्लग-इन लागू करना चाहिए। – beef2k

+1

यहां समाधान आपके उदाहरण में तंत्र के माध्यम से अपने स्वयं के प्लगइन पंजीकृत करने से स्थैतिक lib के उपयोगकर्ताओं को रोकता नहीं है (प्रबंधक आपके मूल उदाहरण में उसी रजिस्टर प्लगइन विधि को कॉल करता है (मैंने इसे ठीक करने के बाद))। यह केवल यह सुनिश्चित करता है कि स्थिर लाइब्रेरी के अंदर भेजे गए प्लगइन प्रबंधक के लिए उपलब्ध हैं जो आपके उपयोगकर्ता लिंक करते हैं (बिना प्लगइन को स्पष्ट रूप से संदर्भित किए बिना) –

1

यह Harald Scheirich's answer पर एक फॉलोअप है।

मैं कुछ प्रयोग किया है, और ऐसा लगता है कि MSVC++ 2005 की रिलीज मोड (लेकिन डिबग मोड), संयोजक, जो LINK documentation के अनुसार करने के लिए /OPT:REF ध्वज भी चालू हो जाएगा किसी भी unreferenced प्रतीकों से निकाले जाने का कारण होगा अंतिम EXE। और, the webpage for __declspec(selectany) इंगित करता है कि वैश्विक वस्तुओं के लिए रचनाकारों को किसी ऑब्जेक्ट के संदर्भ के रूप में नहीं माना जाता है (गलत आईएमएचओ, लेकिन वहां आपके पास है)। तो मेरा अनुमान है कि यह समस्या डीबग बिल्ड के लिए "चला जाता है" - क्या यह सही है?

तो, मुझे लगता है कि __declspec(dllexport) का उपयोग करने का हेराल्ड का सुझाव प्रतीक को "संदर्भित" के रूप में चिह्नित करने का एक सुविधाजनक तरीका है क्योंकि यह स्रोत कोड के अंदर निर्दिष्ट है। अगर किसी कारण से आप प्रतीक निर्यात करने से बचना चाहते हैं, तो मुझे संदेह है कि आप /INCLUDE:mysymbol linker flag का उपयोग करके या /OPT:REF ध्वज को बंद करके एक ही चीज़ को पूरा कर सकते हैं।

+0

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

+0

दिलचस्प। यह एक शर्म की बात है कि यह अधिकार प्राप्त करना बहुत मुश्किल है, क्योंकि ग्लोबल वैरिएबल के कन्स्ट्रक्टर में कक्षा पंजीकृत करना एक प्लगइन सिस्टम विकसित करने के लिए इतना अच्छा, रखरखाव तरीका है। –

+0

हम डीबग और रिलीज बिल्ड में समस्या का सामना कर रहे हैं। और न केवल विजुअल स्टूडियो पर, बल्कि जीसीसी पर भी। – beef2k

0

करें:

  1. exe ​​परियोजना
  2. दोनों "लिंक लायब्रेरी निर्भरता" और स्थापित करने के लिए एक संदर्भ के रूप स्थिर lib परियोजना जोड़ने सच के रूप में "इनपुट के रूप में लिंक लायब्रेरी निर्भरता का उपयोग करें"।

इस देखें: config

जब "इनपुट के रूप में उपयोग लिंक लायब्रेरी निर्भरता" हाँ पर सेट है, निर्भर परियोजनाओं द्वारा उत्पादित .libs के लिए .obj फाइलों में परियोजना प्रणाली लिंक। तो सभी प्रतीकों को रखा जाता है।

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