c# C++ DLL को C++ कार्यों से कॉल करना, लेकिन सी#से नहीं




loadlibrary (2)

मेरे पास tccdvc.dll नामक एक DLL है जो यहां उपलब्ध एसडीके का हिस्सा है:

http://www.commell.com.tw/Download/Driver/Industrial%20Peripheral/Driver/MPX-885/MPX-885%20SDK%20(1.2)/SetupCOMMELL%20MPX-885_20100627.rar

DLL को सी ++ में लिखा गया था और डीएलएल से पता चलता है कि इसे लिंकर संस्करण 6.0 से जोड़ा गया था, इसलिए मुझे लगता है कि यह वीसी ++ 6.0 के साथ लिखा गया था। DLL स्रोत कोड, केवल एक .lib फ़ाइल और एक .h फाइल के साथ नहीं आती है। सभी निर्यात किए गए फ़ंक्शंस को "सी" के रूप में घोषित किया जाता है (इसलिए कोई C ++ नाम समापन नहीं) और APIENTRY के साथ (__stdcall)।

मैंने TCCDvc.dll को एक्सेस करने के लिए Windows XP SP3 (32-बिट) पर विजुअल स्टूडियो 2010 में सी ++ (नॉट।) प्रोग्राम लिखा है I यह ठीक काम करता है, दोनों जब प्रदान की गई। Lib फ़ाइल का उपयोग करते हैं और जब LoadLibrary / GetProcAddress का उपयोग करते हैं मैंने एक सी + + डीएलएल (चलो इसे mywrapper.dll कहते हैं) जो कि tccdvc.dll का उपयोग करता है, और फिर, दो संस्करणों में, .lib फ़ाइल का उपयोग करते हुए, और अन्य का प्रयोग करते हुए LoadLibrary / GetProcAddress। दोबारा, यह ठीक काम करता है यह mywrapper.dll __cdecl कॉलिंग कन्वेंशन का उपयोग करता है। इसमें InitMyWrapperDLL () नामक फ़ंक्शन शामिल हैं जो कि tccdvc.dll को लोड करता है। MyWrapper.dll का संस्करण जो LoadLibrary / GetProcAddress का उपयोग करता है, इस प्रकार कोड है:

typedef int (APIENTRY *TCCPROCTYPE01)();

HMODULE TCCmodule;
TCCPROCTYPE01 Proc_TCC_DVCOpen;

extern "C" __declspec(dllexport) void InitMyWrapperDLL ()
{ TCCmodule = LoadLibrary("tccdvc.dll");
  Proc_TCC_DVCOpen = (TCCPROCTYPE01)GetProcAddress(TCCmodule, "TCC_DVCOpen");
  ...
}

दोबारा, सी ++ फ़्रंट-एंड का उपयोग करके, यह ठीक काम करता है हालांकि, जब इसे सी # (एक ही मशीन पर) से बुलाते हैं, तो LoadLibrary ("tccdvc.dll") कॉल रिटर्न शून्य। सी # में, मैं उपयोग कर रहा हूँ:

[DllImport("mywrapper.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="InitMyWrapperDLL")]
private static extern void InitMyWrapperDLL ();

...

InitMyWrapperDLL();

इसके बजाय प्रदान की गई tccdvc.lib फ़ाइल का उपयोग करते हुए mywrapper.dll को संकलित करते समय, यह त्रुटि कोड 0x8007045a (1114 के रूप में भी ज्ञात) के साथ ही विफल हो जाता है, जिसका अर्थ है कि DLL initialisation विफल हुआ, और यह mywrapper.dll को DLL के नाम के रूप में देता है। यह पता चला है कि विफलता tccdvc.dll के कारण है, जो mywrapper.dll के माध्यम से लोड हो जाती है।

निम्नलिखित में सी # का प्रयोग भी विफल रहता है:

[DllImport("tcc.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="TCC_DVCOpen")]
private static extern Int32 TCC_DVCOpen ();

...

TCC_DVCOpen();

मैंने घोषणा में "असुरक्षित" का भी इस्तेमाल किया है, लेकिन इससे कोई फर्क नहीं पड़ा। अनुमानित, क्योंकि LoadLibrary () विफल रहता है, इसलिए यह TCC_DVCOpen () तक नहीं पहुंचता है ()।

इस समस्या को हल करने के लिए, मैं mywrapper.dll का LoadLibrary / GetProcAddress संस्करण का उपयोग किया और मेरे C # प्रोग्राम में निम्न कोड डाल दिया:

[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary (string lpLibFileName);

[DllImport("kernel32.dll")]
private static extern Int32 GetLastError ();

...

IntPtr hdll1 = LoadLibrary("mywrapper.dll");
IntPtr hdll2 = LoadLibrary("tccdvc.dll");
Int32 errcode = GetLastError();

उसके बाद, hdll1 का मान्य मान है, लेकिन hdll2 0 है। जब .NET 3.5 फ़्रेमवर्क का उपयोग करते हैं, तो GetLastError () 0x8007045a को फिर से देता है, लेकिन जब .NET 4.0 का उपयोग करते हैं, तो GetLastError () 0 (ERROR_SUCCESS) रिटर्न करता है।

मैं अधिक जानकारी प्राप्त करने के लिए सिस्टम मॉनिटर द्वारा सिस्टम मॉनिटर का इस्तेमाल किया और मैं देख सकता हूँ कि tccdvc.dll को सफलतापूर्वक पढ़ा और मैप किया जा रहा है प्रक्रिया मॉनिटर डिस्पले में कुछ भी नहीं है जो मुझे सी # पर उपयोग करते समय विफल रहता है, लेकिन सी ++ का प्रयोग करते समय ऐसा नहीं होता है

कोई विचार? धन्यवाद!


मेरे पास आपके लिए कुछ सुझाव हैं:

  • आप एक सी ++ / सीएलआई कक्षा लिबरी प्रोजेक्ट बना सकते हैं, फिर अपने सी # प्रोजेक्ट में इसका संदर्भ लें।
  • मेरे मामले में मुझे पता चला कि फोन के लिए UnmanagedFunctionPointerAttribute आवश्यक था,
  • एक ऐसा मामला था जो मैं करता हूं, .डीएलएल को कॉल केवल सी # से ही नहीं, केवल। एलआईबी ने मेरे लिए काम किया (जिसका अर्थ है मेरा पहला सुझाव लागू करना)। समस्या निवारण ने मुझे नेतृत्व किया कि 'डीएलएल स्पेस' उस विशेष लाइब्रेरी के लिए उपयुक्त नहीं था।

(अंतिम वाक्य के बारे में: कोई रास्ता नहीं मैं एक सी ++ विशेषज्ञ हूं, वास्तव में यह एकमात्र परियोजना है जो मैंने अभी तक किया है। निश्चित रूप से अधिक विवरण के हकदार हैं, लेकिन मुझे इस समस्या के स्रोत को जानने का ज्ञान नहीं था और न ही ज्ञान था, लेकिन यह तय हो गया क्योंकि मुझे बस इसकी जरुरत है । किसी भी गलती / बेहतर स्पष्टीकरण के लिए धन्यवाद।)

यहाँ कुछ हल है जो मेरी समस्या पर लागू हुआ है:

C # से सी कॉलबैक का उपयोग कैसे करें? अगर आप अपने सभी कोड देखना चाहते हैं तो डीएलएल के लिए लिंक है।

इसके अलावा, कुछ उपकरण जो मेरे लिए इस डोमेन में सहायक रहे हैं:

बल आपके साथ हो :-)


इसलिए, आपका सी कोड काम करता है जब C ++ एप्लिकेशन से कॉल किया जाता है, लेकिन समान कोड विफल हो जाता है जब .NET बाइनरी से कॉल किया जाता है, जहां यह LoadLibrary में विफल रहता है ...

यह सिर्फ एक कूल्हे है, इसलिए मुझे यकीन नहीं है कि आपकी परिस्थितियों का वर्णन किया गया है, लेकिन LoadLibrary में रिश्तेदार डीएलएल नामों के पथ को हल करने के लिए कुछ जटिल मानदंड हैं, जो कुछ पैरामीटर के अनुसार भिन्न हो सकते हैं। मैं उन सभी को अपने सिर के ऊपर से नहीं जानता। ऐसा हो सकता है कि एनईटी बाइनरी के एक्सई मैनिफेस्ट में कुछ ऐसा नियम उन नियमों के अनुसार डीएलएल को खोजने से रोक रहा है। आप PATH वातावरण चर समायोजित करने या एक पूर्ण पथ के साथ DLL को लोड करने का प्रयास कर सकते हैं। (आप GetModuleFileName इत्यादि अपने खुद के कोड का पूर्ण पथ खोजने के लिए उपयोग कर सकते हैं ...)





loadlibrary