2016-08-02 4 views
10

अगर मैं इस तरह एक समारोह की घोषणा:डीएलएल नाम सजावट के बिना __stdcall का उपयोग कर: यह भी क्यों काम करता है?

#ifdef TEST_EXPORTS 
#define TEST_API __declspec(dllexport) 
#else 
#define TEST_API __declspec(dllimport) 
#endif 

TESTAPI int __stdcall myadd(int a, int b); 

DLL में प्रतीक [email protected], जो मेरे लिए एकदम सही समझ में आता है (यहाँ अन्य प्रश्न पढ़ने के कुछ घंटों के बाद, वह है) है।

लेकिन विंडोज पुस्तकालय कुछ अलग करने लगते हैं। वे __stdcall (WINAPI के रूप में छिपे हुए) का भी उपयोग करते हैं, लेकिन डीएलएल में प्रतीकों का कोई नाम सजावट नहीं है। यदि विंडोज़ libs में ऊपर की विधि, प्रतीक myadd होगा।

मेरा अनुमान है कि वे प्रतीकों के उपनाम के लिए एक डीफ़ फ़ाइल का उपयोग करते हैं। लेकिन जब मैं इन डीएलएल में से किसी एक से लिंक करता हूं तो मेरे लिंकर को यह क्यों पता है?

विंडोज हेडर फाइलें इन कार्यों को WINAPI के साथ घोषित करती हैं, इसलिए यदि मैं उन्हें कॉल करता हूं, तो लिंकर को सजाए गए नाम की तलाश करनी चाहिए, क्योंकि यह __stdcall फ़ंक्शन है। फिर भी किसी भी तरह से लिंकर नाम सजावट छोड़ना जानता है।

मैंने इसे एक छोटा डीएलएल लिखकर और डीफ़ फाइल के साथ नाम सजावट को हटाकर इसे दोहराने की कोशिश की है। जैसा कि अपेक्षित है मुझे लिंकर त्रुटियां मिलती हैं क्योंकि लिंकर अभी भी सजाए गए नाम की तलाश में है। मैंने यह सुनिश्चित करने के लिए शुद्ध सी में किया है कि C++ नाम मैंगलिंग इसे प्रभावित नहीं करता है।

संपादित करें: स्पष्ट करने के लिए, MSVC 14.0/VS2015, 32-बिट

+0

ध्यान दें कि x64 नाम सजावट का उपयोग नहीं करता है। –

+0

@ जोनाथनपोटर: * "ध्यान दें कि x64 नाम सजावट का उपयोग नहीं करता है।" * - यह केवल 'बाहरी' सी '' के लिए सच है। सी ++ प्रतीकों में ओवरलोड रिज़ॉल्यूशन के लिए निर्यात नामों को सजाया जाना चाहिए। – IInspectable

उत्तर

6

काम पर कुछ मुश्किल से प्रलेखित जादू यहां नहीं है। आइए कुछ WIN32API फ़ंक्शन देखें, जैसे RegQueryValueExW। यह इस तरह winreg.h फ़ाइल में परिभाषित किया गया है:

WINADVAPI LSTATUS APIENTRY RegQueryValueExW(...); 

कहाँ WIADVAPI एक __declspec(dllimport) और APIENTRY__stdcall नामकरण सम्मेलन के लिए एक उपनाम है। यह भी ध्यान रखें कि शीर्षलेख में सभी कार्यों को extern "C" के रूप में घोषित किया गया है। तो हर तरह से, इस समारोह को नाम सजावट का उपयोग करना चाहिए, और इसका डीएलएल निर्यात [email protected] होना चाहिए। फिर भी जब हम advapi32.dlldumpbin /exports आदेश का उपयोग कर निर्यात देख रहे हैं, हम एक असज्जित नाम देखें:

advapi exports

अब बारीकी से advapi32.lib फ़ाइल dumpbin /headers advapi32.lib आदेश का उपयोग कर परीक्षण कर सकते हैं:

enter image description here

नोट undecorate विनिर्देशक है, जो सजाए गए नाम को अनावृत निर्यात से जोड़ने की अनुमति देता है। आप def फ़ाइल का उपयोग करके EXPORTS अनुभाग के साथ अपरिवर्तित नाम वाले अपने डीएल के लिए एक ही परिणाम प्राप्त कर सकते हैं। अतिरिक्त जानकारी के लिए this आलेख और this answer देखें।

इसके अलावा, ऊपर लिखा गया सब कुछ केवल x86 अनुप्रयोगों के लिए मान्य है। सी x64 बिट वातावरण में काम करता है without name decoration जुड़े हुए हैं: के रूप में निम्न तालिका में दिखाए

एक सी समारोह के लिए सजावट के रूप में, अपने घोषणा में प्रयोग किया जाता बुला सम्मेलन पर निर्भर करता है। यह सजावट प्रारूप भी है जिसका उपयोग तब किया जाता है जब सी ++ कोड बाहरी "सी" लिंकेज घोषित किया जाता है। डिफ़ॉल्ट कॉलिंग सम्मेलन __cdecl है। ध्यान दें कि 64-बिट वातावरण में, फ़ंक्शंस सजाए नहीं जाते हैं।

+0

यही वह है। मैं स्मार्ट होने की कोशिश कर रहा था और सजाए गए नामों को डीफ़ फाइल में डाल दिया था। Lib वास्तव में लापता लिंक है। यह सजाए गए प्रतीक को परिभाषित करता है और अग्रेषित डीएलएल प्रतीक को कॉल करता है। – Stefan

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