c++ - मैं डीएलएल से और उससे सुरक्षित रूप से ऑब्जेक्ट्स, विशेष रूप से एसटीएल ऑब्जेक्ट्स कैसे पास करूं?




windows dll (3)

@ कॉम्प्यूटरफ्रेकर ने एक महान स्पष्टीकरण लिखा है कि एबीआई की कमी सामान्य मामले में डीएलएल सीमाओं में सी ++ ऑब्जेक्ट्स को पार करने से क्यों रोकती है, भले ही टाइप परिभाषा उपयोगकर्ता नियंत्रण में हों और सटीक उसी टोकन अनुक्रम दोनों प्रोग्रामों में उपयोग किया जाए। (दो मामले हैं जो काम करते हैं: मानक-लेआउट कक्षाएं, और शुद्ध इंटरफेस)

सी ++ मानक (मानक टेम्पलेट लाइब्रेरी से अनुकूलित किए गए समेत) में परिभाषित ऑब्जेक्ट प्रकारों के लिए, स्थिति बहुत दूर है। इन प्रकारों को परिभाषित करने वाले टोकन एकाधिक कंपाइलरों में समान नहीं हैं, क्योंकि सी ++ मानक पूर्ण प्रकार की परिभाषा प्रदान नहीं करता है, केवल न्यूनतम आवश्यकताएं। इसके अलावा, इन प्रकार की परिभाषाओं में दिखाई देने वाले पहचानकर्ताओं का नाम लुकअप इसे हल नहीं करता है। यहां तक ​​कि सिस्टम पर जहां सी ++ एबीआई है, मॉड्यूल सीमाओं में ऐसे प्रकारों को साझा करने का प्रयास एक परिभाषा नियम उल्लंघन के कारण भारी अपरिभाषित व्यवहार में होता है।

यह ऐसा कुछ है जो लिनक्स प्रोग्रामर से निपटने के आदी नहीं थे, क्योंकि जी ++ का libstdc ++ एक वास्तविक तथ्य था और लगभग सभी कार्यक्रम इसका इस्तेमाल करते थे, इस प्रकार ओडीआर को संतुष्ट करते थे। क्लैंग के libc ++ ने धारणा तोड़ दी, और फिर सी ++ 11 लगभग सभी मानक पुस्तकालय प्रकारों में अनिवार्य परिवर्तन के साथ आया था।

मॉड्यूल के बीच मानक पुस्तकालय प्रकारों को साझा न करें। यह अपरिभाषित व्यवहार है।

मैं क्लास ऑब्जेक्ट्स, खासकर एसटीएल ऑब्जेक्ट्स को सी ++ डीएलएल से कैसे पास करूं?

मेरे आवेदन को डीएलएल फाइलों के रूप में तीसरे पक्ष के प्लगइन के साथ बातचीत करनी है, और मैं इन प्लगइन्स के साथ किस कंपाइलर के साथ बनाया गया है उसे नियंत्रित नहीं कर सकता। मुझे पता है कि एसटीएल वस्तुओं के लिए कोई गारंटीकृत एबीआई नहीं है, और मैं अपने आवेदन में अस्थिरता पैदा करने के बारे में चिंतित हूं।


आप डीएलएल सीमाओं में एसटीएल ऑब्जेक्ट्स को सुरक्षित रूप से पास नहीं कर सकते हैं, जब तक कि सभी मॉड्यूल (.EXE और .DLLs) एक ही सी ++ कंपाइलर संस्करण और सीआरटी की समान सेटिंग्स और स्वाद के साथ बनाए जाते हैं, जो अत्यधिक बाधा है, और स्पष्ट रूप से आपका मामला नहीं है।

यदि आप अपने डीएलएल से ऑब्जेक्ट-ओरिएंटेड इंटरफ़ेस का पर्दाफाश करना चाहते हैं, तो आपको सी ++ शुद्ध इंटरफेस का खुलासा करना चाहिए (जो COM के समान है)। CodeProject पर इस दिलचस्प लेख को पढ़ने पर विचार करें:

Howto: डीएलएल से सी ++ कक्षाओं का निर्यात करें

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


यहां कुछ जवाब सी ++ कक्षाओं को वाकई डरावना ध्वनि देते हैं, लेकिन मैं एक वैकल्पिक दृष्टिकोण साझा करना चाहता हूं। कुछ अन्य प्रतिक्रियाओं में वर्णित शुद्ध वर्चुअल सी ++ विधि वास्तव में आपके विचार से क्लीनर बन जाती है। मैंने अवधारणा के चारों ओर एक संपूर्ण प्लगइन प्रणाली बनाई है और यह वर्षों से बहुत अच्छी तरह से काम कर रहा है। मेरे पास एक "प्लगइन प्रबंधक" श्रेणी है जो लोडलिब () और GetProcAddress () (और लिनक्स समकक्षों को क्रॉस प्लेटफ़ॉर्म बनाने के लिए निष्पादन योग्य) का उपयोग करके निर्दिष्ट निर्देशिका से डीएलएस को गतिशील रूप से लोड करता है।

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

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

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

अच्छी खबर यह है कि कोड की कुछ हद तक आप एसटीएल तार, वैक्टर, और अन्य कंटेनर कक्षाओं को लपेटने के लिए पुन: प्रयोज्य जेनेरिक कक्षाएं और इंटरफेस बना सकते हैं। वैकल्पिक रूप से, आप अपने इंटरफ़ेस में फ़ंक्शन जोड़ सकते हैं जैसे GetCount () और GetVal (n) लोगों को सूचियों के माध्यम से लूप करने दें।

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

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

तो कहानी का नैतिक है ... कुछ चरम परिस्थितियों के अपवाद के साथ, आपको इंटरफेस के प्रभारी एक व्यक्ति की आवश्यकता होती है जो सुनिश्चित कर सकता है कि एबीआई सीमा आदिम प्रकारों से साफ रहती है और ओवरलोडिंग से बचाती है। यदि आप उस शर्त के साथ ठीक हैं, तो मैं कंपाइलरों के बीच डीएलएल / एसओएस में कक्षाओं में इंटरफेस साझा करने से डर नहींूंगा। कक्षाओं को सीधे साझा करना == परेशानी, लेकिन शुद्ध वर्चुअल इंटरफेस साझा करना इतना बुरा नहीं है।







abi