2009-10-04 11 views
8

डीएलएल (डीएलएल में कन्स्ट्रक्टर) से कुछ वर्ग कैसे बनाएं? (С ++) या डीएल से गतिशील रूप से कक्षा को कैसे लोड करें?डीएलएल (डीएल में कन्स्ट्रक्टर) से कुछ वर्ग कैसे बनाएं? (С ++)

+0

आप उससे मिलते-जुलते हेडर फाइल की क्या ज़रूरत है और/या पुस्तकालय फ़ाइल डीएल तक पहुंचने के लिए? –

+0

हाँ मेरे पास मेरे हेडर और स्रोत हैं – SomeUser

उत्तर

3

का जवाब आपके सवाल का सख्ती से, आप एक extern "सी" समारोह है कि निर्माता का परिणाम देता है जोड़ने की जरूरत:

extern "C" foo* __declspec(dllexport) new_foo(int x) { 
    return new foo(x); 
} 

फिर अपने स्रोत में आप GetProcAddr "new_foo" पर उपयोग कर सकते हैं समारोह कॉल करने के लिए ।

3

आपको डीएलएल से एक फ़ंक्शन निर्यात करने की आवश्यकता होगी जो निर्माता को कॉल करता है और नई ऑब्जेक्ट देता है।

कंक्रीट सी ++ प्रकारों को फ़ंक्शन पैरामीटर के रूप में उपयोग करने से बचने का प्रयास करें; डीएलएल का विचार यह है कि आप उन्हें स्वतंत्र रूप से अपडेट कर सकते हैं, लेकिन एक अपग्रेड किया गया कंपाइलर std :: स्ट्रिंग को अलग-अलग रख सकता है, जिससे रनटाइम पर असंगतता हो सकती है।

यह COM की जड़ पर है, उदाहरण के लिए - सीमित प्रकार की प्रणाली और ऑब्जेक्ट्स के उदाहरण प्राप्त करने के लिए मानक निर्यातित फ़ंक्शन।

+0

टीटी लगता है जैसे डीएलएल का स्रोत उसके नियंत्रण में नहीं है। –

+0

डीएलएल स्रोत मेरे नियंत्रण में है – SomeUser

+0

यदि वर्ग का उपयोग करने का इरादा है, तो इसे शायद पहले से ही __declspec (dllexport) के साथ संकलित किया जाना चाहिए, इसलिए यह केवल हेडर फ़ाइल को __declspec (dllimport) में रखने के लिए हेडर फ़ाइल को समझाने का विषय है कक्षा परिभाषा। यदि नहीं, तो आप हमेशा हेडर फ़ाइल को संशोधित कर सकते हैं। – JesperE

10

डीएलएल बनाने के दौरान आपको __declspec(dllexport) कीवर्ड का उपयोग करके अपनी कक्षा घोषित करने की आवश्यकता है। DLL उपयोग करते समय, वर्ग __declspec(dllimport) साथ घोषित किए जाने की जरूरत:

#ifdef COMPILING_DLL 
#define DECLSPEC_CLASS __declspec(dllexport) 
#else 
#define DECLSPEC_CLASS __declspec(dllimport) 
#endif 

class DECLSPEC_CLASS MyClass 
{ 
... 
} 

जब DLL संकलित किया गया है, तो आप परिभाषित करता है की सूची में -DCOMPILING_DLL जोड़ना चाहिए।

कक्षा का उपयोग करते समय, आपको डीएलएल के साथ स्थाई रूप से लिंक करना होगा, यानी मुख्य प्रोग्राम में आयात लाइब्रेरी mydll.lib को पास करना होगा।

यदि आप रनटाइम पर DLL लोड करना चाहते हैं, तो आपको DLL में एक सी-फ़ंक्शन होना चाहिए जो ऑब्जेक्ट बनाता है और इसे आपके लिए लौटाता है। डीएलएल में गतिशील रूप से एक कन्स्ट्रक्टर को देखने का कोई तरीका नहीं है (GetProcAddress() का उपयोग करके)।

+1

क्या आप अंतिम वक्तव्य के लिए स्रोत उद्धृत कर सकते हैं? AFAIK एक ctor एक उलझन में नाम है, और आप उस नाम का उपयोग कर GetProcAddress को कॉल कर सकते हैं। आपको क्या रोक देगा? – MSalters

+0

हां, तकनीकी रूप से आप सही हैं। – JesperE

3

__declspec का उपयोग कर वर्ग की हर विधि के निर्यात के बजाय, आप यह भी सच है पर भरोसा कर सकते कि संकलक vtable के माध्यम से आभासी कार्यों आह्वान कर सकते हैं, तो उदाहरण के लिए:

//note: no __declspec 
class IPublicInterface 
{ 
    virtual ~IPublicInterface() = 0; 
    virtual void SomeMethod() = 0; 
}; 

//note: no __declspec 
class SomeClass : IPublicInterface 
{ 
    virtual ~SomeClass() { ... } 
    virtual void SomeMethod() { ... } 
}; 

//note: this is the only method which needs to be exported from the DLL 
IPublicInterface* createSomeClass() 
{ 
    return new SomeClass(); 
} 
+0

इंटरफ़ेस/फ़ैक्टरी पैटर्न अच्छा है, खासकर यदि आप 'GetProcAddress' का उपयोग करने जा रहे हैं और मैन्युअल रूप से प्रबंधित हैं .def निर्यात तालिका –

+0

चूंकि स्मृति DLL में आवंटित की गई है, हो सकता है कि वहां' फ्रीसम क्लास (IPublicInterface *) भी हो सुनिश्चित करें कि स्मृति सही ढंग से मुक्त हो गया है? – Robert

+0

मुझे लगता है कि यह उत्तर गलत है और इसे हटाया जाना चाहिए। आप प्लगइन सीमा पर एक पॉलिमॉर्फिक ऑब्जेक्ट पास नहीं कर सकते हैं, सिवाय इसके कि जब प्लगइन और एप्लिकेशन दोनों में सटीक उसी कंपाइलर का उपयोग किया जाता है। –

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