2010-01-27 9 views
8

मैं यूनिक्स प्रकार प्लेटफार्म पर सी ++ में COM के कस्टम कार्यान्वयन को कार्यान्वित करने के लिए देख रहा हूं ताकि मुझे गतिशील रूप से लोड ऑब्जेक्ट उन्मुख कोड को लिंक और लिंक किया जा सके। मुझे लगता है कि यह कार्यक्षमता के समान सेट पर आधारित होगा जो POSIX लोड करने और डीएलएल यानी dlopen, dlsym और dlclose को कॉल करने के लिए प्रदान करता है।कस्टम COM कार्यान्वयन?

मैं समझता हूं कि COM का सामान्य विचार यह है कि आप कुछ कार्यों यानी QueryInterface, AddRef और रिलीज़ को एक सामान्य डीएल (Kernel32.dll) में लिंक करते हैं जो आपको इंटरफेस तक पहुंचने की अनुमति देता है जो फ़ंक्शन पॉइंटर्स की एक तालिका है उस ऑब्जेक्ट के लिए पॉइंटर के साथ encapsulated जिसके लिए फ़ंक्शन पॉइंटर्स को कॉल किया जाना चाहिए। इन कार्यों को अज्ञात के माध्यम से उजागर किया गया है जिन्हें आप का उत्तराधिकारी होना चाहिए।

तो यह सब कैसे काम करता है? ऑब्जेक्ट उन्मुख कोड को गतिशील रूप से लिंक और लोड करने का कोई बेहतर तरीका है? एक डीएलएल से विरासत कैसे काम करती है - क्या बेस क्लास के लिए प्रत्येक कॉल को एक खुला सदस्य समारोह होना चाहिए यानी निजी/संरक्षित/जनता को केवल अनदेखा किया जाता है?

मैं सी ++ और टेम्पलेट मेटा-प्रोग्रामिंग में काफी अच्छी तरह से परिचित हूं और पहले से ही पूरी तरह से प्रतिबिंबित सी ++ सिस्टम है। मैं सदस्य गुण, सदस्य कार्य और वैश्विक/स्थैतिक कार्यों को बढ़ावा देता हूं जो बढ़ावा देता है।

उत्तर

4

मैं यूनिक्स प्रकार प्लेटफार्म पर सी ++ में COM के कस्टम कार्यान्वयन को कार्यान्वित करने के लिए देख रहा हूं ताकि मुझे गतिशील रूप से लोड ऑब्जेक्ट उन्मुख कोड को लिंक करने और लिंक करने की अनुमति मिल सके। मुझे लगता है कि यह कार्यक्षमता के समान सेट पर आधारित होगा जो POSIX लोड करने और डीएलएल यानी dlopen, dlsym और dlclose को कॉल करने के लिए प्रदान करता है।

अपने सबसे सरल स्तर पर, COM इंटरफेस के साथ लागू किया गया है। C++ में, यदि आप शुद्ध आभासी, या सार आधार वर्ग के विचार के साथ सहज महसूस कर रहे हैं, तो आप पहले से ही C++

struct IMyInterface { 
    void Method1() =0; 
    void Method2() =0; 
}; 

COM क्रम अतिरिक्त सेवाओं है कि करने के लिए आवेदन का एक बहुत प्रदान करता है में एक इंटरफेस को परिभाषित करने के लिए कैसे पता खिड़कियां पर्यावरण लेकिन वास्तव में एक मिनी एप्लिकेशन में "मिनी" COM को कार्यान्वित करने की आवश्यकता नहीं होती है, जो पारंपरिक रूप से डलोपेन, डीएलएसआईएम इत्यादि की अनुमति से अधिक ओओ इंटरफ़ेस से कनेक्ट करने के साधन के रूप में

COM ऑब्जेक्ट्स को .dll में लागू किया जाता है। , .so या .dylib फ़ाइलें आपके प्लेटफ़ॉर्म के आधार पर। इन फ़ाइलों को कम से कम एक फ़ंक्शन को निर्यात करने की आवश्यकता है जो मानक है: DllGetClassObject

अपने पर्यावरण में आप इसे प्रोटोटाइप कर सकते हैं, हालांकि आप चाहते हैं कि विंडोज़ पर COM रनटाइम के साथ इंटरऑप करना स्पष्ट रूप से नाम और पैरामीटर को कॉम मानक के अनुरूप होना चाहिए ।

मूल विचार यह है कि यह एक GUID - 16 बाइट्स के लिए एक सूचक को पारित किया जाता है जो विशिष्ट रूप से किसी विशेष वस्तु को सौंपा जाता है, और यह बनाता है (GUID पर आधारित) और फैक्ट्री ऑब्जेक्ट के आईसीएलएएसफ़ैक्टरी * को देता है।

आईसीएलएएसफ़ैक्टरी :: CreateInstance विधि कहलाते समय ऑब्जेक्ट के उदाहरण बनाने के लिए, कॉम रनटाइम द्वारा कारखाने ऑब्जेक्ट का उपयोग किया जाता है।

तो, अब तक आप

  • पारित कर दिया GUID में यह देखने के लिए जाँच करता है कि एक गतिशील पुस्तकालय कम से कम एक प्रतीक, नाम "DllGetClassObject" निर्यात (या उसके किसी भिन्न रूप)
  • एक DllGetClassObject विधि है और जो वस्तु का अनुरोध किया जा रहा है, और फिर एक 'नई CSomeObjectClassFactory "
  • एक CSomeObjectClassFactory कार्यान्वयन कि औजार (से निकला) IClassFactory करता है, और CreateInstance विधि के लिए' नई 'CSupportedObject के उदाहरण लागू करता है।
  • CSomeSupportedObject जो IU अज्ञात से प्राप्त एक कस्टम, या COM परिभाषित इंटरफ़ेस लागू करता है। यह महत्वपूर्ण है क्योंकि IClassFactory :: CreateInstance को एक आईआईडी पारित किया जाता है (फिर से, इस समय एक इंटरफ़ेस को परिभाषित करने वाला 16byte अद्वितीय आईडी) कि उसे ऑब्जेक्ट पर QueryInterface की आवश्यकता होगी।

मैं समझता हूँ कॉम के सामान्य विचार है कि आप कुछ कार्यों से लिंक है कि IE QueryInterface, AddRef और एक आम dll (Kernel32.dll) जो तब अभिगम अंतरफलक जो सिर्फ एक मेज हैं करने की अनुमति देता में रिलीज फ़ंक्शन पॉइंटर्स का ऑब्जेक्ट पर पॉइंटर के साथ encapsulated जिसके लिए फ़ंक्शन पॉइंटर्स के साथ कॉल किया जाना चाहिए। इन कार्यों को अज्ञात के माध्यम से उजागर किया गया है जिन्हें आप का उत्तराधिकारी होना चाहिए।

असल में, COM OLE32.dll द्वारा कार्यान्वित किया गया है जो CoCreateInstance नामक "सी" एपीआई का खुलासा करता है। ऐप ने CoCreateInstance को एक GUID पास किया, जो इसे विंडोज रजिस्ट्री में दिखता है - जिसमें GUID का डीबी है -> "पथ से डीएल" मैपिंग। ओएलई/कॉम फिर डीएलएल लोड करता है (डीएलओपीएन) डीएलजी में गुजरता है, जो कि GUID में गुजरता है, यह सुनिश्चित करता है कि सफल होता है, ओएलई/कॉम फिर CreateInstance को कॉल करता है और परिणामी इंटरफ़ेस को ऐप पर देता है।

तो यह सब कैसे काम करता है? ऑब्जेक्ट उन्मुख कोड को गतिशील रूप से लिंक और लोड करने का कोई बेहतर तरीका है? एक डीएलएल से विरासत कैसे काम करती है - क्या बेस क्लास के लिए प्रत्येक कॉल को एक खुला सदस्य समारोह होना चाहिए यानी निजी/संरक्षित/जनता को केवल अनदेखा किया जाता है?

कक्षा में प्रत्येक विधि को "सजाए गए" प्रतीक के रूप में निर्यात करके डीएल/एस/डिलिब कार्यों से सी ++ कोड की निहित विरासत। विधि का नाम कक्षा के साथ सजाया गया है, और प्रत्येक पैरामीटर का प्रकार। यह वही तरीका है जो प्रतीकों को स्थिर पुस्तकालयों (.a या .lib फाइल iirc) से निर्यात किया जाता है। स्टेटिक या गतिशील पुस्तकालय, "निजी, संरक्षित आदि" हमेशा कंपाइलर द्वारा लागू किया जाता है, हेडर फ़ाइलों को पार्स कर रहा है, कभी भी लिंकर नहीं।

मैं काफी अच्छी तरह से सी में निपुण कर रहा हूँ ++ और टेम्पलेट मेटा प्रोग्रामिंग और पहले से ही एक पूरी तरह से चिंतनशील सी ++ प्रणाली यानी सदस्य गुण, सदस्य कार्य करता है और वैश्विक/स्थिर कार्यों को बढ़ावा देने का उपयोग करता है। DLLs कि लोड पर लोड किए गए हैं, कार्यावधि में dlopen के माध्यम से नहीं -

C++ वर्गों आमतौर पर केवल स्थिर लिंकेज के साथ DLLs से निर्यात किया जा सकता है। COM यह सुनिश्चित करके सी ++ इंटरफेस को गतिशील रूप से लोड करने की अनुमति देता है कि COM में उपयोग की जाने वाली सभी डेटाटाइप या तो पॉड प्रकार हैं, या शुद्ध वर्चुअल इंटरफेस हैं।यदि आप इस नियम को तोड़ते हैं, तो एक इंटरफ़ेस को परिभाषित करके जो किसी बूस्ट या किसी अन्य प्रकार की ऑब्जेक्ट को पारित करने का प्रयास करता है, आप जल्द ही ऐसी परिस्थिति में आ जाएंगे जहां संकलक/लिंकर को हेडर फ़ाइल से अधिक की आवश्यकता होगी ताकि यह पता चल सके कि क्या हो रहा है और आपका ध्यान से तैयार "कॉम" डीएल को कार्य करने के लिए स्थिर या अंतर्निहित रूप से लिंक करना होगा।

COM का दूसरा नियम किसी गतिशील लाइब्रेरी सीमा के पार किसी ऑब्जेक्ट का स्वामित्व कभी नहीं पास करता है। यानी किसी डीएलएल से इंटरफ़ेस या डेटा कभी वापस न करें, और ऐप को इसे हटाने की आवश्यकता है। इंटरफेस को सभी को अज्ञात, या कम से कम एक रिलीज() विधि को लागू करने की आवश्यकता है, जो ऑब्जेक्ट को इसे हटाने की अनुमति देता है। किसी भी लौटाए गए डेटा प्रकारों में भी एक प्रसिद्ध डी-आवंटक होना चाहिए - यदि आपके पास "CreateBlob" नामक विधि के साथ एक इंटरफेस है, तो शायद "DeleteBlob" नामक एक दोस्त विधि होनी चाहिए।

2

वास्तव में समझने के लिए कि COM कैसे काम करता है, मैं डॉन बॉक्स द्वारा "आवश्यक COM" पढ़ने का सुझाव देता हूं। sscli में CORBA प्रलेखन पर

3

देखो, System.ComponentModel पर, मोज़िला codebase की XPCOM भागों। मिगुएल डी इक्का ने ग्नोम में ओएलई की तरह कुछ लागू किया जिसे Bonobo कहा जाता है जो भी उपयोगी हो सकता है।

हालांकि आप सी ++ के साथ क्या कर रहे हैं, इस पर निर्भर करते हुए, आप यहेया जैसे सी ++ के लिए प्लगइन ढांचे को देखना चाहेंगे। मेरा मानना ​​है कि बूस्ट के पास कुछ समान है।

संपादित करें: pugg फिलहाल येहिया से बेहतर बनाए रखा लगता है। मैंने हालांकि कोशिश नहीं की है।

6

ध्यान में रखने की कुछ बातें:

  • कॉम की शक्ति आईडीएल और MIDL संकलक से काफी हद तक आता है। यह आपके लिए जेनरेट किए गए सभी सी/सी ++ बॉयलरप्लेट के साथ ऑब्जेक्ट्स और इंटरफेस की एक verry succint परिभाषा की अनुमति देता है।

  • COM पंजीकरण। विंडोज़ पर क्लास आईडी (सीएलएसआईडी) रजिस्ट्री में दर्ज की जाती है जहां वे निष्पादन योग्य से जुड़े होते हैं। आपको यूनिक्स पर्यावरण में समान कार्यक्षमता प्रदान करनी होगी।

  • पूरे IUnknown कार्यान्वयन (अर्थात् कोई RTTI) काफी तुच्छ है, QueryInterface जो जब सी में लागू काम करता है के लिए छोड़कर।

  • COM का एक और पहलू आईडीिसपैच है - यानी देर से बाध्य विधि आमंत्रण और खोज (केवल प्रतिबिंब पढ़ें)।

XPCOM पर एक नज़र डालें क्योंकि यह पर्यावरण की तरह एक बहु-मंच COM है। यह वास्तव में उन चीजों में से एक है जो आप अन्य प्रौद्योगिकियों का लाभ उठाने से बेहतर हैं। यह कहीं और बेहतर समय बिताया जा सकता है।

3

COM का मूल डिज़ाइन बहुत आसान है।

  1. सभी COM ऑब्जेक्ट में एक या अधिक इंटरफेस
  2. सभी इंटरफेस IUnknown इंटरफ़ेस से प्राप्त कर रहे के माध्यम से उनकी कार्यक्षमता का पर्दाफाश, इस प्रकार सभी इंटरफेस उनके आभासी समारोह के पहले 3 तरीके के रूप में QueryInterface, AddRef & रिलीज तरीकों एक ज्ञात क्रम में तालिका
  3. सभी ऑब्जेक्ट्स IU अज्ञात
  4. किसी ऑब्जेक्ट का समर्थन करने वाले किसी भी इंटरफ़ेस को किसी अन्य इंटरफ़ेस से पूछताछ की जा सकती है।
  5. इंटरफेस विश्व स्तर पर अद्वितीय पहचानकर्ता से पहचाने जाते हैं, इन IIDs GUIDs या CLSIDs हैं, लेकिन वे सब वास्तव में एक ही बात कर रहे हैं। http://en.wikipedia.org/wiki/Globally_Unique_Identifier

कहाँ कॉम जटिल हो जाता है कि यह कैसे की इजाजत दी इंटरफेस प्रक्रिया है जहाँ वस्तु रहता है बाहर से कहा जाने के साथ संबंधित है। COM marshalling एक बुरा, बालों वाली, जानवर है। इस तथ्य से और भी इतना बनाया गया कि COM एकल थ्रेडेड और बहु ​​थ्रेडेड प्रोग्रामिंग मॉडल दोनों का समर्थन करता है।

COM का विंडोज कार्यान्वयन ऑब्जेक्ट्स को पंजीकृत करने की अनुमति देता है (विंडोज रजिस्ट्री का मूल उपयोग COM के लिए था)। कम से कम COM रजिस्ट्री में COM ऑब्जेक्ट के लिए अद्वितीय GUID और लाइब्रेरी (डीएलएल) के बीच मैपिंग होता है जिसमें इसका कोड होता है।

इसके लिए काम करने के लिए। डीएलएल जो COM ऑब्जेक्ट्स को कार्यान्वित करते हैं, उनमें क्लासफैक्टरी होना चाहिए - डीएलएल में एक मानक नाम वाला एक एंट्री पॉइंट जिसे डीएलएल लागू करने वाले COM ऑब्जेक्ट्स में से एक बनाने के लिए कहा जा सकता है। (प्रैक्टिस में, विंडोज COM को इस प्रविष्टि बिंदु से आईसीएलएएसएफ़ैक्ट्री ऑब्जेक्ट मिलता है, और अन्य COM ऑब्जेक्ट्स बनाने के लिए इसका उपयोग करता है)।

ताकि 10 प्रतिशत दौरे है, लेकिन वास्तव में इस को समझने के लिए, आप डॉन बॉक्स द्वारा Essential COM पढ़ने की जरूरत है।

2

आपको (अभी तक) Boost.Extension लाइब्रेरी में रुचि हो सकती है।

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