जैसा कि आप बता सकते हैं, 64-बिट विंडोज़ नामों में सजाए गए नहीं हैं।
32-बिट __cdecl
और __stdcall
प्रतीकों में, प्रतीक नाम अंडरस्कोर द्वारा प्रीपेड किया जाता है। आपके उदाहरण फ़ंक्शन के 32-बिट संस्करण के लिए निर्यात किए गए नाम में पिछला '@ 8' पैरामीटर सूची में बाइट्स की संख्या है। यह वहां है क्योंकि आपने __stdcall
निर्दिष्ट किया है। यदि आप __cdecl
कॉलिंग कन्वेंशन (सी/सी ++ कोड के लिए डिफ़ॉल्ट) का उपयोग करते हैं, तो आपको वह नहीं मिलेगा।
#if _WIN64
#define DecorateSymbolName(s) s
#else
#define DecorateSymbolName(s) "_" ## s
#endif
तो बस
pfnConnect = GetProcAddress(hDLL, DecorateSymbolName("Connect"));
pfnOtherFunc = GetProcAddress(hDLL, DecorateSymbolName("OtherFunc"));
या कुछ इसी तरह की (त्रुटि उदाहरण में छोड़े गए जाँच) के साथ फोन: आप __cdecl
का उपयोग करते हैं, यह बहुत आसान है की तरह कुछ के साथ GetProcAddress()
रैप करने के लिए बनाता है। आसान जा रहा है बनाए रखने के लिए, अगर विकास के दौरान एक निर्यात समारोह परिवर्तन के हस्ताक्षर, आप अपने #define
के साथ चारों ओर पेंच की जरूरत नहीं है करने के लिए
__declspec(dllexport) long __cdecl Connect(char * name, long size);
__declspec(dllexport) long __cdecl OtherFunc(int someValue);
इसके अलावा: ऐसा करने के लिए, के रूप में अपने निर्यात कार्यों घोषित करने के लिए याद रैपर।
डाउनसाइड: यदि विकास के दौरान किसी दिए गए फ़ंक्शन की पैरामीटर सूची में बाइट्स की संख्या में परिवर्तन होता है, तो यह फ़ंक्शन आयात करने वाले एप्लिकेशन द्वारा पकड़ा नहीं जाएगा क्योंकि हस्ताक्षर बदलने से नाम बदल नहीं जाएगा। निजी तौर पर, मुझे नहीं लगता कि यह एक मुद्दा है क्योंकि 64-बिट बिल्ड उसी परिस्थितियों में उड़ाएगा, वैसे भी नामों को सजाया नहीं गया है। आपको बस यह सुनिश्चित करना होगा कि आपका एप्लिकेशन डीएलएल के सही संस्करण का उपयोग कर रहा है।
यदि डीएलएल का उपयोगकर्ता सी ++ का उपयोग कर रहा है, तो आप सी ++ क्षमताओं का उपयोग करके चीजों को बेहतर तरीके से लपेट सकते हैं (पूरे स्पष्ट रूप से लोड लाइब्रेरी को रैपर वर्ग में लपेटें, उदा।):
class MyDLLWrapper {
public:
MyDLLWrapper(const std::string& moduleName); // load library here
~MyDLLWrapper(); // free library here
FARPROC WINAPI getProcAddress(const std::string& symbolName) const {
return ::GetProcAddress(m_hModule, decorateSymbolName(symbolName));
}
// etc., etc.
private:
HMODULE m_hModule;
// etc.
// ...
};
वास्तव में आप इस तरह के एक रैपर वर्ग के साथ बहुत कुछ कर सकते हैं, यह सिर्फ एक उदाहरण है।
संपादित करें पर: के बाद से ओपी टिप्पणी में PInvoke का उपयोग कर उल्लेख किया है - अगर किसी को ऐसा करने के लिए फैसला करता है, मत भूलना जब PInvoke का उपयोग कर [DllImport]
घोषणा में CallingConvention = CallingConvention.Cdecl
जोड़ने के लिए। __cdecl
अप्रबंधित सी/सी ++ के लिए डिफ़ॉल्ट हो सकता है, लेकिन प्रबंधित कोड के लिए डिफ़ॉल्ट नहीं है।
इसलिए यदि मैं सही ढंग से समझता हूं तो मुझे केवल इसे डीएल-प्रोजेक्ट में जोड़ना होगा और फिर मेरे अनुप्रयोग और सी # PInvokes डीएलएस का उपयोग कर परिवर्तन के बिना काम करेंगे? यदि अन्य प्रस्तावित समाधानों की तुलना में इस समाधान के लिए कोई डाउनसाइड है? – dbostream
ठीक है, मैं इनपुट के लिए धन्यवाद। – dbostream
@dbostream: मूल सी ++ डीएलएल से शुद्ध सी इंटरफेस के साथ फ़ंक्शंस निर्यात करने के लिए, मुझे _DEecorated_ फ़ंक्शन नाम प्राप्त करने के लिए सुविधाजनक .DEF फ़ाइलें मिलती हैं। –