2009-12-10 12 views
8

मेरे पास एक डीएलएल है जिसे होस्ट एप्लिकेशन में एसटीएल कंटेनर में संग्रहीत डेटा तक पहुंचने की आवश्यकता है। चूंकि सी ++ में कोई मानक एबीआई नहीं है, और मैं विभिन्न कंपाइलर्स का समर्थन करना चाहता हूं, एप्लिकेशन और डीएलएल के बीच इंटरफेस को मूल रूप से सादे-पुराने डेटा रखना है।डीएलएल सीमा पर एसटीएल सूची का खुलासा कैसे करें?

वैक्टरों के लिए यह अपेक्षाकृत सरल है। आप बस वेक्टर की स्मृति ब्लॉक लौट सकते हैं, क्योंकि यह contigious होने की गारंटी है:

// To return vector<int> data 
virtual void GetVectorData(const int*& ptr, size_t& count) const 
{ 
    if (!vec.empty()) 
     ptr = &(vec.front()); 

    count = vec.size(); 
} 

अब DLL कि इंटरफ़ेस के माध्यम से वेक्टर के डेटा के लिए सुरक्षित रीड ओनली पहुंच हो सकता है। डीएलएल सामग्री को अपनी सदिश में भी कॉपी करने के लिए लपेट सकता है।

हालांकि एसटीएल सूचियों (और डेक) के बारे में क्या? क्या डीएलएल सीमा के माध्यम से पहुंच की अनुमति देने का कोई और आसान तरीका है? या मुझे किसी प्रकार का GetFirst()/GetNext() इंटरफ़ेस का सहारा लेना होगा? मुझे कई सूचियों के लिए ऐसा करने की आवश्यकता हो सकती है, इसलिए वेक्टर के रूप में सरल समाधान होना अच्छा लगेगा।

उत्तर

7

शायद आप सूची/डेक इटरेटर के लिए "हैंडल" जैसे कुछ पास कर सकते हैं? ये हैंडल प्रकार अपारदर्शी होंगे और एक हेडर फ़ाइल में घोषित किए जाएंगे जो आप उपयोगकर्ताओं को भेज देंगे। आंतरिक रूप से, आपको हैंडलर को सूची/डेक करने के लिए हैंडल मानों को मैप करना होगा।

ListHandle lhi = GetListDataBegin(); 
const ListHandle lhe = GetListDataEnd(); 

while (lhi != lhe) 
{ 
    int value = GetListItem(lhi); 
    ... 
    lhi = GetNextListItem(lhi); 
} 
1

आवेदन और DLL के बीच इंटरफेस मूल रूप से सादे पुराने डेटा रहने के लिए है।

आवश्यक नहीं है। आपको यह सुनिश्चित करना होगा कि एक ही कंपाइलर संस्करण का उपयोग किया जाए। साथ ही, एसटीएल ऑब्जेक्ट्स के लेआउट को प्रभावित करने वाली सेटिंग्स का निर्माण डीएल और एप्लिकेशन के बीच बिल्कुल समान है।

यदि आप जंगली में डीएलएल को छोड़ना चाहते थे, तो आप डीएल सीमाओं में एसटीएल को उजागर करने के लिए चिंतित होने का अधिकार रखते हैं। यदि, हालांकि, सबकुछ आपके नियंत्रण में है और पूरी तरह से आंतरिक है (या यदि आप कठोर रूप से तृतीय पक्ष निर्माण सेटिंग्स/कंपाइलर को लागू कर सकते हैं) तो आपको ठीक होना चाहिए।

+0

आप सही हैं कि अगर मैं सभी संकलन सेटिंग्स समान हैं तो मैं इससे दूर हो सकता हूं। लेकिन यह एक प्लगइन आर्किटेक्चर के लिए है और मैं विभिन्न कंपाइलर्स का समर्थन करना चाहता हूं। मैंने इसे स्पष्ट करने के लिए प्रश्न संपादित किया है। – AshleysBrain

+0

मैं इसके साथ सहमत हूं, लेकिन शायद आपको तनाव होना चाहिए कि यह केवल लेआउट नहीं है - कोड को संकलक के उसी संस्करण के साथ संकलित किया जाना चाहिए, ताकि नए तरीके और कार्यान्वयन के तरीके को कार्यान्वित किया जा सके। –

+0

यदि आप निर्माण सेटिंग/कंपाइलर संस्करणों को कठोर रूप से लागू कर रहे हैं और सबकुछ आपके नियंत्रण में है, तो, स्थिर पुस्तकालयों का उपयोग करके डीएलएल का बनाम क्या लाभ है और सबकुछ एक निष्पादन योग्य में जोड़ना है? –

10

आप DLLs के बीच एसटीएल वस्तुओं गुजरती हैं और विभिन्न compilers समर्थन करता है, तो आप सावधान कर रहे हैं जहाँ आप प्रत्येक एसटीएल प्रकार का दृष्टांत कर सकते हैं: मूल रूप से, उपयोगकर्ता की तरह कोड लिखने होगा। आपको कुछ बुद्धिमान "DLLEXPORT" मैक्रोज़ की आवश्यकता है - मैं वीसी और जीसीसी का सफलतापूर्वक समर्थन करने के लिए निम्न सेट का उपयोग करता हूं।

#ifdef WIN32 
#ifdef MYDLLLIB_EXPORTS  // DLL export macros 
#define MYDLLLIB_API __declspec(dllexport) 
#define MYDLLLIB_TEMPLATE 
#else 
#define MYDLLLIB_API __declspec(dllimport) 
#define MYDLLLIB_TEMPLATE extern 
#endif 
#else      // Not windows --- probably *nix/bsd 
#define MYDLLLIB_API 
#ifdef MYDLLLIB_EXPORTS 
#define MYDLLLIB_TEMPLATE 
#else 
#define MYDLLLIB_TEMPLATE extern 
#endif 
#endif // WIN32 

अपने डीएलएल को संकलित करते समय, MYDLLLIB_EXPORTS को परिभाषित करें। DLL में आप तो प्रत्येक एसटीएल प्रकार आप उपयोग करना चाहते हैं, उदाहरण के, सूची या तार

अपने DLL के
MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::vector<std::string>; 
MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::list<std::string>; 

उपभोक्ताओं की वैक्टर (जो परिभाषित MYDLLLIB_EXPORTS नहीं है) के लिए कर सकते हैं का दृष्टांत तो देखेंगे

extern template class __declspec(dllimport) std::vector<std::string>; 

और अपने स्वयं के तुरंत चालू करने के बजाय आपके डीएलएल से निर्यात किए गए बाइनरी कोड का उपयोग करें।

+0

यह एक बहुत ही रोचक समाधान है - क्या मुझे std :: vector :: iterator और std :: list :: iterator के लिए ऐसा करना होगा? क्या मेजबान EXE से डीएलएल उपभोग करने वाले एसटीएल कक्षाओं के लिए यह वही तरीका है? – AshleysBrain

+0

आपको इटरेटर को तुरंत चालू करने की आवश्यकता नहीं है क्योंकि जब आप एक विशिष्ट एसएलएल कंटेनर क्लास को तुरंत चालू करते हैं तो आपको कंटेनर क्लास के भीतर सभी कक्षाओं के लिए कोड भी मिलता है। मेजबान EXE से एसटीएल कक्षाओं का उपभोग करने के बारे में नहीं जानते - मैंने व्यक्तिगत रूप से ऐसा नहीं किया है, इसलिए यदि आप इस विधि का पालन करना चाहते हैं तो आपको एक साधारण परीक्षण के साथ थोड़ा सा प्रयोग करना होगा। – mcdave

+2

यहां यह एमएसडीएन में है: http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q168958 – k06a

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