2009-06-27 14 views
6

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

क्या विंडोज-निर्भर एपीआई (जो डीएलएस में काम करने की गारंटी है) का उपयोग करने का एकमात्र समाधान है? सी एपीआई पहले से मौजूद है और परिपक्व है, लेकिन यूनिक्स पीओवी से डिजाइन किया गया था, ज्यादातर (और अभी भी यूनिक्स पर काम करना है)।

उत्तर

0

विभिन्न रनटाइम्स के साथ समस्या हल करने योग्य नहीं है क्योंकि FILE * संरचना विंडोज सिस्टम पर एक रनटाइम से संबंधित है।

लेकिन अगर आप लिखना एक छोटा सा आवरण इंटरफ़ेस आपके किया है और यह वास्तव में चोट नहीं करता है।

stdcall IFile* IFileFactory(const char* filename, const char* mode); 

class IFile { 

    virtual fwrite(...) = 0; 
    virtual fread(...) = 0; 

    virtual delete() = 0; 
} 

यह हर जगह डीएलएल सीमाओं पारित करने के लिए बचाया जाता है और वास्तव में चोट नहीं पहुंचाता है।

पी.एस सावधान रहो, अगर आप dll सीमाओं के पार अपवाद फेंकने शुरू .:। यदि आप विंडोज ओएस पर कुछ डिज़ाइन क्रिएटियंस पूरा करते हैं तो यह शांत तरीके से काम करेगा लेकिन कुछ अन्य लोगों पर असफल हो जाएगा।

1

न तो मौजूदा उत्तर सही है: विंडोज़ पर निम्नलिखित को देखते हुए: आपके पास दो डीएलएल हैं, प्रत्येक स्थिर रूप से सी/सी ++ मानक पुस्तकालयों के दो अलग-अलग संस्करणों से जुड़ा हुआ है।

इस मामले में, आपको एक डीएलएल में सी/सी ++ मानक पुस्तकालय द्वारा बनाई गई संरचनाओं के लिए पॉइंटर्स पास नहीं करना चाहिए। कारण यह है कि इन संरचनाओं दो C/C++ मानक पुस्तकालय कार्यान्वयन के बीच अलग-अलग हो सकता है।

दूसरी चीज जो आपको नहीं करना चाहिए वह एक डीएलएल से नए या मॉलोक द्वारा आवंटित एक सूचक है जो दूसरे में आवंटित किया गया था। ढेर मैनेजर भी अलग-अलग लागू किया जा सकता है।

नोट, आप डीएलएल के बीच पॉइंटर्स का उपयोग कर सकते हैं - वे बस स्मृति को इंगित करते हैं। यह मुफ़्त है कि मुद्दा है।

अब, आप पाते हैं कि यह काम करता है, लेकिन यदि ऐसा होता है, तो आप बस भाग्यशाली हैं। यह आपको भविष्य में समस्याएं पैदा करने की संभावना है।

आपकी समस्या का एक संभावित समाधान गतिशील रूप से CRT से लिंक कर रहा है। उदाहरण के लिए, आप गतिशील रूप से MSVCRT.DLL से लिंक कर सकते हैं। इस तरह आपका डीएलएल हमेशा एक ही सीआरटी का उपयोग करेगा।

नोट, मेरा सुझाव है कि डीएलएल के बीच सीआरटी डेटा संरचनाओं को पारित करने का यह सबसे अच्छा अभ्यास नहीं है। आप देखना चाहते हैं कि क्या आप चीजों को बेहतर तरीके से कारक बना सकते हैं।

नोट, मैं लिनक्स/यूनिक्स विशेषज्ञ नहीं हूं - लेकिन आपके पास उन ओएस पर भी वही समस्याएं होंगी।

+0

मैं समस्याओं को समझता हूं - मैं इस समस्या के उत्तर के लिए पूछ रहा हूं :) मैं ऐसे समाधान की उम्मीद कर रहा था जो मौजूदा सी एपीआई (हस्ताक्षर में FILE * के साथ) को बदलने में नहीं लगता है, लेकिन ऐसा लगता है कि वहां है अगर मैं एक ही सी रनटाइम के खिलाफ लिंक करने के लिए सबकुछ गारंटी नहीं दे सकता? हालांकि समस्या सैद्धांतिक रूप से यूनिक्स पर समान है, लेकिन यह शायद ही कभी एक मुद्दा है क्योंकि केवल एक सी रनटाइम है। मुझे FILE * से गुजरने में एक भी समस्या नहीं थी, पुस्तकालयों के बीच यूनिक्स पर फाइल डिस्क्रिप्टर - बहुत से सी एपीआईएस इस तरह से डिजाइन किए गए हैं और उन ओएस पर बेकार ढंग से काम करते हैं। –

+0

यदि एपीआई के हस्ताक्षर में FILE * होना अच्छा अभ्यास नहीं है, तो आप फ़ाइल स्ट्रीम से कैसे निपटते हैं? क्या आपको फ़ाइलों को खोलने और बंद करने के लिए फ़ंक्शंस को निर्यात करने की आवश्यकता है यदि आपके द्वारा कॉल किए गए डीएल में कुछ फ़ंक्शन हैं जो आंतरिक रूप से fprintf और अन्य कार्यों को FILE * की अपेक्षा करते हैं? –

+0

मैंने सुझाव दिया था समाधान :) सीआरटी को स्थिर रूप से लिंक न करें। MSVCRT.DLL से लिंक करें। मैं आश्चर्यचकित हूं कि लिनक्स, यूनिक्स या मैक पर सभी सीआरटी पुस्तकालयों को दोषपूर्ण काम करने की गारंटी दी गई थी। मुझे लगता है कि आप भी भाग्यशाली रहे हैं। – Foredecker

0

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

मुझे पूरा यकीन नहीं है कि FILE * की सीमाएं क्या हैं, लेकिन मुझे लगता है कि समस्या मॉड्यूल में सीआरटी आवंटन के समान ही है। एमएसवीसीआरटी फाइल ऑपरेशंस को संभालने के लिए आंतरिक रूप से Win32 का उपयोग करता है, और अंतर्निहित फ़ाइल हैंडल को उसी प्रक्रिया के भीतर प्रत्येक मॉड्यूल से उपयोग किया जा सकता है। जो काम नहीं कर सकता है वह एक फाइल को बंद कर रहा है जो किसी अन्य मॉड्यूल द्वारा खोला गया था, जिसमें संभावित रूप से अलग सीआरटी पर फ़ाइल संरचना को मुक्त करना शामिल है।

यदि मैं एपीआई बदल रहा हूं तो मैं क्या करूँगा, अभी भी एक विकल्प है, डीएलएल के भीतर बनाए गए किसी भी संभावित "ऑब्जेक्ट" के लिए निर्यात क्लीनअप फ़ंक्शंस है। ये क्लीनअप फ़ंक्शन दिए गए ऑब्जेक्ट के निपटारे को उस तरीके से संभाल लेंगे जो उस डीएलएल के भीतर बनाए गए तरीके से मेल खाता है। यह उपयोग के संदर्भ में डीएलएल को बिल्कुल पोर्टेबल भी बना देगा। तब केवल एक ही चिंता होगी कि यह सुनिश्चित कर रहा है कि डीएलएल का उपयोगकर्ता नियमित रूप से नियमित सीआरटी के बजाय आपके क्लीनअप कार्यों का उपयोग करता है। यह कई चालों का उपयोग करके किया जा सकता है, जो एक और प्रश्न के लायक हैं ...

2

आपने सी ++ समाधान नहीं सी के लिए कहा।

सामान्य विधि (रों) सी में बात इस तरह का करने के लिए कर रहे हैं:

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

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

इस तरह कुछ सरल चाल आप अपने सी DLLs इंटरफ़ेस को पूरी तरह मेजबान सीआरटी से स्वतंत्र कर सकते हैं के साथ

- या वास्तव में मेजबान सी में या बिल्कुल सी ++ लिखे जाने की आवश्यकता होती है।

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