2008-08-25 27 views
8

मैं/सी ++ DLL एक सी लिख रहा हूँ और कुछ कार्य करता है जो मैं इसअतिभारित कार्यों में सी ++ DLL डीईएफ़ फ़ाइल

LIBRARY "MyLib" 
EXPORTS 
    Foo 
    Bar 
कोड के साथ

के रूप में परिभाषित की तरह एक .def फ़ाइल उपयोग करने से पहले किया है निर्यात करना चाहते हैं इस, के लिए उदाहरण:

int Foo(int a); 
void Bar(int foo); 

हालांकि, क्या मैं एक ओवरलोड) की तरह फू की विधि (घोषित करने के लिए चाहते हैं:

int Foo(int a, int b); 

घ के रूप में ef फ़ाइल में केवल फ़ंक्शन का नाम है और पूर्ण प्रोटोटाइप नहीं है, मैं नहीं देख सकता कि यह अधिभारित कार्यों को कैसे संभालेगा। क्या आप सिर्फ एक प्रविष्टि का उपयोग करते हैं और फिर लोडलाब्रिरी() में उचित प्रोटोटाइप फ़ंक्शन पॉइंटर में गुजरते समय आप जो ओवरलोडेड संस्करण चाहते हैं उसे निर्दिष्ट करते हैं?

संपादित करें: जवाब के रूप में गैर-डीईएफ़ (__declspec) विधि में चिह्नित किए गए ... मुझे पता है यह वास्तव में समस्या का उपयोग कर समाधान नहीं करता है: स्पष्ट है कि, इस Windows दृश्य स्टूडियो का उपयोग कर 2005

संपादित करें पर है डीफ़ फाइलों को मैं चाहता था, लेकिन ऐसा लगता है कि डीफ़ फाइलों का उपयोग कर कोई (आधिकारिक) समाधान नहीं है। सवाल खुल जाएगा, हालांकि, अगर किसी को कुछ पता है तो हमारे पास ओवरलोडेड फ़ंक्शंस और डीफ़ फाइलें नहीं हैं।

उत्तर

9

कोड में ही, उन कार्यों को चिह्नित करें जिन्हें आप __declspec (dllexport) का उपयोग करके निर्यात करना चाहते हैं। उदाहरण के लिए:

#define DllExport __declspec(dllexport) 

int DllExport Foo(int a) { 
    // implementation 
} 
int DllExport Foo(int a, int b) { 
    // implementation 
} 

यदि आप ऐसा करते हैं, तो आपको .def फ़ाइल में फ़ंक्शंस सूचीबद्ध करने की आवश्यकता नहीं है।

int Foo(int a, int b = -1) 

इसका मतलब यह है ख है कि आप संकेत मिलता है कि यह अप्रयुक्त है उपयोग कर सकते हैं के लिए एक मूल्य मौजूद है:

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

संपादित करें (एडम हैइल): __declspec का उपयोग करने के लिए सही __dllspec के रूप में सही नहीं था इसलिए मैं इसे आधिकारिक उत्तर के रूप में चिह्नित कर सकता था ... यह काफी करीब था।

संपादित करें (ग्रीम): ओह - मेरे टाइपो को सही करने के लिए धन्यवाद!

+0

क्या होगा यदि हम एक गतिशील DLL के साथ GetProcAddress() का उपयोग कर रहे हैं? – null

+2

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

11

फ़ंक्शन ओवरलोडिंग एक सी ++ सुविधा है जो नाम मैंगलिंग (लिंकर त्रुटि संदेशों में गुप्त कार्य नाम) पर निर्भर करती है।

LIBRARY "TestDLL" 
EXPORTS 
    [email protected]@[email protected] 
    [email protected]@[email protected] 

के लिए

void Foo(int x); 
void Foo(int x, int y); 

काम करने के लिए तो से सी ++ फ़ंक्शन नाम कॉपी लगता है:

डीईएफ़ फ़ाइल में घायल नाम लिखकर, मैं लिंक और चलाने के लिए अपने परीक्षण परियोजना प्राप्त कर सकते हैं त्रुटि संदेश और उन्हें अपनी डीफ़ फ़ाइल में लिखें। हालांकि, असली सवाल यह है कि आप एक डीफ फाइल का उपयोग क्यों करना चाहते हैं और __declspec (dllexport) के साथ नहीं जाते?

उलझन वाले नाम गैर पोर्टेबल हैं, मैंने वीसी ++ 2008 के साथ परीक्षण किया।

+0

दिलचस्प दृष्टिकोण। गैर पोर्टेबल द्वारा आपका मतलब विजुअल स्टूडियो के विभिन्न संस्करणों में है? कौन सा सुझाव देगा कि वे संस्करणों के बीच अपना नाम मैंगलिंग योजनाएं बदल सकते हैं? – jxramos

+0

@jxramos मुझे यकीन नहीं है कि वे वास्तव में नाम मैंगलिंग योजना बदल सकते हैं या नहीं। लेकिन मुझे संदेह है कि यह एक और कंपाइलर पर स्विच करते समय उसी तरह काम करेगा, जब तक कि संकलक वीसी के व्यवहार को अनुकरण करने की कोशिश नहीं करता। – Timbo

+0

यह निश्चित रूप से केवल एक वीसी ++ चीज है क्योंकि मुझे नहीं लगता कि अन्य कंपाइलर डीफ़ फाइलों का उपयोग करते हैं। अगर मुझे याद है कि किसी ने मुझे एक बार बताया है कि माइक्रोसॉफ्ट के पास यह डीएलएल इंटरफ़ेस विचार है जहां उपयोगकर्ता चयनित तत्वों को डीफ़ फाइल या __declspec के माध्यम से सार्वजनिक रूप से उजागर किया जाता है, जबकि यूनिक्स में उनके * .so फ़ाइलों के साथ सार्वजनिक एपीआई के साथ सबकुछ खुलासा होता है। उनके पास लॉजिकल पब्लिक एपीआई और लाइब्रेरी के सार्वजनिक एपीआई के बीच अंतर नहीं है। WinXX टिप्पणी के साथ – jxramos

2

एक ओवरलोडेड फ़ंक्शन को निर्यात करने की भाषा या संस्करण अज्ञेय तरीका नहीं है क्योंकि मैंगलिंग सम्मेलन संकलक के प्रत्येक रिलीज के साथ बदल सकता है।

यह एक कारण है कि अधिकांश WinXX फ़ंक्शंस में * एक्स या * 2 जैसे मज़ेदार नाम होते हैं।

+0

दिलचस्प पृष्ठभूमि! – jxramos

3

आप जो चाहते हैं उसे करने का कोई आधिकारिक तरीका नहीं है, क्योंकि डीएल इंटरफ़ेस एक सी एपीआई है।

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

8

मुझे एक समान समस्या थी इसलिए मैं इसे भी पोस्ट करना चाहता था।

  1. आमतौर पर

    extern "C" __declspec(dllexport) void Foo(); 
    

    का उपयोग कर एक समारोह नाम निर्यात करने के लिए ठीक है। यह आमतौर पर नाम .def फ़ाइल की आवश्यकता के बिना unmangled नाम निर्यात करेगा। हालांकि, कुछ अपवाद जैसे __stdcall फ़ंक्शन और अधिभारित फ़ंक्शन नाम हैं।

  2. आप (के रूप में कई एपीआई कार्यों के लिए किया जाता है) __stdcall सम्मेलन उपयोग करने के लिए तो

    extern "C" __declspec(dllexport) void __stdcall Foo(); 
    

    _Foo की तरह एक घायल नाम निर्यात करेगा @ 4 एक समारोह की घोषणा है। इस मामले में आपको निर्यात किए गए नाम को एक आंतरिक उलझन में स्पष्ट रूप से मानचित्र करने की आवश्यकता हो सकती है।

ए। एक असंगत नाम कैसे निर्यात करें। एक .def फ़ाइल में जोड़ने

---- 
EXPORTS 
    ; Explicit exports can go here 

    Foo 
----- 

यह एक आंतरिक समारोह फू के लिए एक "सबसे अच्छा मैच" खोजने के लिए और इसे निर्यात करने की कोशिश करेंगे। जहां केवल एक foo है ऊपर मामले में यह @ 4

मानचित्रण

फू = _Foo पैदा करेगा के रूप में DUMPBIN/निर्यात

के माध्यम से देखने के किया जा सकता है यदि आप एक समारोह का नाम आप तो अतिभारित है प्रविष्टिनाम [= internalname] वाक्यविन्यास का उपयोग करके एक उलझन नाम निर्दिष्ट करके .def फ़ाइल में आप जो फ़ंक्शन चाहते हैं उसे स्पष्ट रूप से कहने की आवश्यकता हो सकती है। जैसे

---- 
EXPORTS 
    ; Explicit exports can go here 

    [email protected] 
----- 

बी .def फ़ाइलों का एक विकल्प यह है कि आप #pragma का उपयोग करके नाम "स्थान" निर्यात कर सकते हैं।

#pragma comment(linker, "/export:[email protected]") 

सी एक तीसरा विकल्प extern "सी" के रूप में unmangled निर्यात किए जाने फू का सिर्फ एक संस्करण की घोषणा करने के लिए है। विवरण के लिए here देखें।

2

निर्यात के लिए Systax परिभाषा है:

entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA] 

entryname समारोह या चर के नाम का आप निर्यात करना चाहते है। यह आवश्यक है। यदि आपके द्वारा निर्यात किया गया नाम डीएलएल में नाम से अलग है, तो डीएलएल में निर्यात का नाम आंतरिक नाम के साथ निर्दिष्ट करें।

उदाहरण के लिए, यदि आपके DLL) एक समारोह, func1 (निर्यात करता है और आप इसे func2() के रूप में इस्तेमाल किया जा करना चाहते हैं, तो आप निर्दिष्ट होगा:

EXPORTS 
func2=func1 

बस (निर्भरता वॉकर का उपयोग) घायल नाम देखने और अपने स्वयं के कार्यों का नाम निर्दिष्ट करें।

स्रोत: http://msdn.microsoft.com/en-us/library/hyx1zcd3(v=vs.71).aspx

संपादित करें: इस गतिशील DLLs, जहां हम GetProcAddress() का उपयोग करने के लिए स्पष्ट रूप Dll में एक कार्यों लाने के लिए की जरूरत है के लिए काम करता है।

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