2010-08-26 9 views
9

dll निर्यात हैडरइमारत 64 बिट dll के साथ एक चेतावनी

extern "C" 
void _declspec(dllexport) __stdcall foo(); 

.def फ़ाइल

EXPORTS 
foo   @1 

जब मैं 64 बिट का निर्माण config द्वारा dll का निर्माण, मैं इस चेतावनी को पूरा।

चेतावनी एलएनके 4197: निर्यात 'foo' कई बार निर्दिष्ट; पहले विनिर्देश का उपयोग

लेकिन अगर मैं 32 बिट बिल्ड कॉन्फ़िगर द्वारा डीएलएल बनाता हूं, तो चेतावनी कभी नहीं होती है।
समस्या क्या है? अंतर क्या है।

इंटरफेस के लिए dll हेडर में, हम आम तौर पर इस कलाओं,

#ifdef EXPORT_DLL 
#define BASICAPI _declspec(dllexport) 
#else 
#define BASICAPI _declspec(dllimport) 
#endif //_EXPORT_DLL 

का उपयोग लेकिन अगर डीईएफ़ फ़ाइल भी मौजूद है, हम हमेशा चेतावनी को पूरा जब हम 64 बिट dll का निर्माण कर रहे हो जाएगा।
तो, क्या हमें इस तरह के कोड लिखना चाहिए?

#ifdef EXPORT_DLL 
#define BASICAPI 
#else 
#define BASICAPI _declspec(dllimport) 
#endif //_EXPORT_DLL 

यह अच्छी तरह से काम करता है। लेकिन यह मुझसे परिचित नहीं है।
मुझे अपनी राय दें।

उत्तर

11

आम तौर पर एक ही फ़ंक्शन के लिए दो बार निर्यात निर्दिष्ट करने का अच्छा अभ्यास नहीं है। यदि आपके पास पहले से __declspec(dllexport) है तो आपको एक .def फ़ाइल में निर्यात निर्दिष्ट करने की आवश्यकता नहीं है। इसके विपरीत, यदि आपके पास .def फ़ाइल में सूचीबद्ध निर्यात है, तो __declspec(dllexport) की आवश्यकता नहीं है।

मेरा मानना ​​है कि चेतावनी के लिए कारण 86 में बनाता है कि है, __declspec(dllexport) एक अग्रणी अंडरस्कोर के साथ सजाया नाम निर्यात कर रहा है, लेकिन 64-बिट संकलक एक अग्रणी अंडरस्कोर के साथ नाम को सजाने नहीं करता है, डुप्लिकेट के लिए अग्रणी। इसे सत्यापित करने के लिए, आप निर्भरता वॉकर में 32-बिट डीएलएल देख सकते हैं और आपको दो निर्यात किए गए फ़ंक्शंस, "foo" और "_foo" देखना चाहिए।

+2

'64-बिट कंपाइलर नामों को सजाने नहीं करता है 'मुझे यह नहीं पता था। यही कारण था! धन्यवाद। – Benjamin

+0

वैसे, मैं टिप्पणी बॉक्स में इटालिक फ़ॉन्ट का उपयोग कैसे कर सकता हूं। – Benjamin

+0

यह * नामों को सजाने * करता है, यह सिर्फ 32-बिट कंपाइलर (यानी अग्रणी अंडरस्कोर के बिना) को अलग-अलग सजाता है। आप अलग-अलग नामों के साथ दो बार फ़ंक्शन निर्यात कर सकते हैं (यही वह है जो मुझे आपके 32-बिट बिल्डों में होने की उम्मीद है) चेतावनी इसलिए है क्योंकि 64-बिट बिल्ड में, '__declspec' और .def फ़ाइल दोनों के परिणामस्वरूप * निर्यात किया गया नाम - इसलिए उनमें से एक को अनावश्यक माना जाता है। –

5

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

इसके अलावा, EXPORT_DLL जैसे जेनेरिक मैक्रो का उपयोग करना खतरनाक है क्योंकि इसका मतलब है कि आप एक डीएलएल नहीं बना सकते हैं, जो एक और डीएल का उपयोग करता है, बिना किसी डीएलएल के दोनों प्रतीकों के सभी प्रतीकों को निर्यात करने की कोशिश कर रहा है।

DevStudio स्वचालित रूप से dll परियोजनाओं पर एक प्रतीक बनाता है: <PROJECT>_EXPORTS यह आसान और सुरक्षित एक निर्यात मैक्रो बनाने के लिए कर रही है:

#ifdef EXPORT 
#undef EXPORT 
#endif 
#ifdef PROJECTNAMEHERE_EXPORTS 
#define EXPORT __declspec(dllexport) 
#else 
#define EXPORT __declspec(dllimport) 
#endif 

EXTERN_C EXPORT void __stdcall Function1(void); 
EXTERN_C EXPORT void __cdecl Function2(...); 
     EXPORT void Function3(void); 

कार्य 1 & 2 क्रमशः [email protected] और Function2 रूप GetProcAddress के साथ मिल जा सकता है। फ़ंक्शन 3 को एक कंपाइलर विशिष्ट मैंगल्ड नाम के माध्यम से निर्यात किया जा रहा है जो कुछ ऐसा दिखाई देगा: @[email protected]@[email protected]। यह नाम फ़ंक्शन के प्रत्येक ओवरलोड के लिए अलग है, इस प्रकार यह काम पर ओवरलोडिंग की अनुमति देता है।

इसकी महत्वपूर्ण __declspec रूप .def फ़ाइलों का नाम mangling परवाह नहीं है पता करने के लिए और सिर्फ निर्यात होता Function1, Function2 और Function3

+1

आपका पहला पैराग्राफ मैं अपने * पहले पैराग्राफ के साथ कहने की कोशिश कर रहा था, लेकिन आपने कहा कि यह मुझसे बेहतर है, +1 :) –

+0

अच्छा जवाब और टिप्पणी। +1 :) – Benjamin

+0

मैं 64 बिट चीज के बारे में नहीं जानता था। –

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