2008-12-14 10 views
18

मैं डीएलएल के साथ .def फ़ाइलों का उपयोग करने के बिंदु को समझ नहीं रहा हूं।.def फ़ाइलें सी/सी ++ डीएलएल

ऐसा लगता है कि यह आपके डीएलएल कोड (यानी स्पष्ट __declspec (dllexport) के भीतर स्पष्ट निर्यात का उपयोग करने की आवश्यकता को प्रतिस्थापित करता है) हालांकि मैं इनका उपयोग नहीं करते समय एक lib फ़ाइल उत्पन्न करने में असमर्थ हूं जो बाद में लिंकर समस्याओं का उपयोग करते समय बनाता है DLL।

तो क्लाइंट एप्लिकेशन से लिंक करते समय आप .defs का उपयोग कैसे करते हैं, क्या वे हेडर या .lib फ़ाइल का उपयोग करने की आवश्यकता को प्रतिस्थापित करते हैं?

उत्तर

17

मेरी समझ यह है कि .def फ़ाइलें निर्यात किए गए कार्यों के नियमों को स्पष्ट रूप से निर्दिष्ट करने में सक्षम होने के अतिरिक्त लाभ के साथ __declspec (dllexport) वाक्यविन्यास का विकल्प प्रदान करती हैं। यह उपयोगी हो सकता है यदि आप केवल कुछ टर्मिनल द्वारा कुछ फ़ंक्शंस निर्यात करते हैं, जो फ़ंक्शन के बारे में अधिक जानकारी नहीं दिखाता है (उदाहरण: ओएस आंतरिक डीएलएल के निर्यात कार्यों में से केवल ऑर्डिनल द्वारा)।

reference page देखें।

ध्यान दें कि .def फ़ाइल में नाम बाइनरी में नामों से मेल खाना चाहिए। तो यदि आप 'बाहरी "सी" {...}' के साथ सी या सी ++ का उपयोग करते हैं, तो नामों को उलझाया नहीं जाएगा; अन्यथा आपको DLL उत्पन्न करने के लिए उपयोग किए गए कंपाइलर के विशिष्ट संस्करण के लिए सही उलझन वाले नामों का उपयोग करना होगा। __declspec() फ़ंक्शन यह सब स्वचालित रूप से करता है।

+0

एम एम क्लूनी ने कहा: "और क्या?"। +1। एक विंडोज डेवलपर के रूप में, मेरा अनुभव यह है कि डीईएफ फाइलें "पुरानी तरीका" हैं, और उन्हें बहिष्कृत किया जाना चाहिए (यदि पहले से नहीं है)। – paercebal

+0

हां, .def फ़ाइलें __declspec भाषा एक्सटेंशन को पूर्ववत करती हैं। एक .def फ़ाइल में ऐसा कुछ भी नहीं है जिसे आप या तो __declspec या #pragmas से नहीं कर सकते हैं। इसमें फैंसी लिंकर ट्रिक्स शामिल हैं जैसे एनीमेशन का नामकरण या अग्रेषण करना। –

3

मैंने डीएलएल के साथ बहुत कुछ नहीं किया है, लेकिन मेरी समझ यह है कि निर्यात किए गए सी ++ कार्यों के लिए, आपने "__declspec (dllexport)" का उपयोग किया और निर्यात किए गए सी कार्यों के लिए आपको .def फ़ाइल लिखनी चाहिए। ऐसा शायद इसलिए है क्योंकि सी ++ फ़ंक्शन ओवरलोडिंग का समर्थन करते हैं, लेकिन सी फ़ंक्शन नहीं करते हैं।

+1

हां। ओवरलोडिंग क्षमता = सजाए गए नाम जो .def फ़ाइल में निर्दिष्ट करने के लिए परेशान हैं। यहां सी और सी ++ के बीच कोई मौलिक अंतर नहीं है, लेकिन एक काफी ergonomic और सांस्कृतिक अंतर है। –

3

.DEF फ़ाइलें 16-बिट विंडो में अधिक आम थीं, जहां आमतौर पर यह निर्दिष्ट करने का एकमात्र तरीका था कि कौन से प्रतीकों को निर्यात किया जाना चाहिए।

इसके अतिरिक्त, उन्होंने नाम के बजाय क्रमिक मूल्य (@ 1, @ 2 इत्यादि) द्वारा निर्यात निर्दिष्ट करने का साधन प्रदान किया। प्रतीकों को देखने की यह विधि तब प्रयोग की जाती थी जब प्रदर्शन वास्तव में महत्वपूर्ण था, जैसे वीडियो ड्राइवरों में।

3

मेरी समझ यह है कि .def फ़ाइलें वास्तव में निर्दिष्ट नहीं करती हैं कि सभी एपीआई को निर्यात करने की आवश्यकता है। इसमें सिर्फ एपीआई निर्यात और उनके सामान्य संख्याएं शामिल हैं। यदि आप वास्तव में एक विशेष एपीआई निर्यात करना चाहते हैं, तो आपको घोषणा में एपीआई और __declspec (dllimport) की परिभाषा में __declspec (dllexport) निर्दिष्ट करने की आवश्यकता है।

डीफ़ फाइल का लाभ यह है कि, यह आपको पहले से ही वास्तविक डीएलएस के साथ बैकवर्ड संगतता बनाए रखने में मदद करता है। यानी यह एपीआई के लिए क्रमिक संख्या बनाए रखता है। मान लीजिए कि आप डीएलएल में एक नया एपीआई जोड़ते हैं, तो लिंकर आपकी .def फ़ाइल को ne wapi के लिए क्रमिक संख्या को जीनरेट करता है जैसे पुराने एपिस के लिए सामान्य संख्या बरकरार है।

तो, यदि क्लाइंट कोड नवीनतम डीएल का उपयोग करता है, तो यह मौजूदा एपीआई को तोड़ता नहीं है।

7

अभी भी रुचि रखने वालों के लिए ... डीएलएल और डीफ़ फ़ाइल से लिंक करने में सक्षम होने के लिए आपको एक lib फ़ाइल की भी आवश्यकता है। विंडोज़ में इसे 'LIB' टूल का उपयोग करके डीफ़ से बनाया जा सकता है। ऐसा करने के कमांड लाइन तरीके के उदाहरण के लिए नीचे देखें।

lib /machine:i386 /def:sqlite3.def 

आशा है कि इससे दूसरों की मदद मिलेगी।

+0

+1। यह वही था जो मैं – fmuecke

+4

के लिए देख रहा था वास्तव में, यह काम नहीं किया। निम्नलिखित आदेश क्या काम था: 'lib /DEF:sqlite3.def/मशीन: X86/सबस्टेस्टम: विंडोज/एलटीसीजी/नोलोगो '। परिणामस्वरूप .lib आसानी से sqlite3.dll के खिलाफ गतिशील रूप से लिंक करने के लिए उपयोग किया जा सकता है। – fmuecke

22

मुझे पोर्टेबल डीएलएल बनाने में उपयोगी होने के लिए __declspec (dllexport) और .def फ़ाइल दोनों का उपयोग मिल गया है, यानी डीएलएल जिन्हें एक अलग कंपाइलर या विभिन्न कंपाइलर सेटिंग्स के साथ संकलित कोड से बुलाया जा सकता है।

बस अपने फ़ंक्शन घोषणाओं पर __declspec (dllexport) डालने से उन कार्यों को आपके डीएलएल (कम से कम विंडोज़) द्वारा "निर्यात" किया जाएगा ताकि उन्हें डीएलएल के बाहर से बुलाया जा सके।

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

void foo(int i); 

लग सकती है के रूप में "_foo @ 4" निर्यात किया जा रहा है अगर तुम सम्मेलन और .def फ़ाइल उपयोग बुला के बारे में सावधान नहीं हैं।

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

HANDLE dllHandle = LoadLibrary("mydll.dll"); 
void* fooFcnPtr = GetProcAddress(dllHandle, "foo"); 
कुछ उपयुक्त त्रुटि मामले निश्चित रूप से जाँच के साथ

!

आपके डीएलएल के निर्माण के दौरान आपके फ़ंक्शन घोषणाओं पर एक .def फ़ाइल प्लस __stdcall, __declspec (dllexport) और बाहरी "सी" का उपयोग सुनिश्चित करेगा कि उपरोक्त क्लाइंट-साइड कोड कंपेलरों और कंपाइलर सेटिंग्स की विस्तृत श्रृंखला के लिए काम करेगा ।

+1

सी ++ कार्यों के नाम को रोकने के लिए, आपको उन्हें 'बाहरी "सी" '] (http://stackoverflow.com/search?q=extern+c) घोषित करना चाहिए। – sbi

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