2012-01-19 7 views
5

मैं एक देशी DLL में निम्नलिखित समारोह हेडर रख:मार्शल एक अहस्ताक्षरित चार * एक dll से समारोह लौटने, सी # में

unsigned char* Version_String() 

मैं इसे एक सी # परियोजना से कॉल करने के लिए कोशिश कर रहा हूँ, मैं कोशिश की है निम्नलिखित कॉल (के रूप में यहां अन्य इसी तरह के सवाल पर पाया):

[DllImport("BSL430.dll", CharSet=CharSet.Ansi)] 
public extern static UIntPtr Version_String(); 

और मैं निम्न अपवाद बार आ रही है:

का प्रयास किया गया पढ़ने के लिए या prot लिखने के लिए ected स्मृति। यह अक्सर एक संकेत है कि अन्य स्मृति भ्रष्ट है।

अगले कोशिश निम्नलिखित था और मैं एक ही अपवाद:

[DllImport("BSL430.dll", CharSet=CharSet.Ansi)] 
[return : MarshalAs(UnmanagedType.LPStr)] 
public extern static string Version_String(); 

मैं इस समस्या के समाधान पाने के लिए नहीं कर पा रहे। किसी भी तरह की सहायता का स्वागत किया जाएगा!

संपादित करें: इस तरह

मैं DLL कोड यहाँ के रूप में यह एक एनडीए के अंतर्गत आता है नहीं दे सकता है, लेकिन समारोह मैं फोन कर रहा हूँ लगता:

unsigned char versionString[50]; 

__declspec(dllexport) unsigned char* Version_String() 
{ 
    if(check_hardware_stuff()) 
    { 
     strcpy((char *) versionString, "version_string_bla_bla"); 
     versionString[5] = stuff; 
    } 
    else if (other_check()) 
    { 
     //will return empty string, that should be filled with '\0' 
    } 
    else 
    { 
     strcpy((char *) versionString, "ERROR"); 
    } 
    return versionString; 
} 

मैं विशेष रूप से डीएलएल कार्यान्वयन का शौक नहीं है, लेकिन मुझे इसे "जैसा है" का उपयोग करने की आवश्यकता है। जब भी मैं वापसी मूल्य के साथ क्या करता हूं, भले ही मैं VersionString() पर कॉल करने का प्रयास करता हूं, तो मुझे अपवाद फेंक दिया जाता है।

+0

शायद आप गलत [कॉलिंग कन्वेंशन] (http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention.aspx) का उपयोग कर रहे हैं? – svick

+0

क्या आपका डीएल मल्टीबाइट वर्णसेट विकल्प के साथ संकलित किया गया था? –

+1

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

उत्तर

8

अद्यतन

अद्यतन सवाल है, विभिन्न टिप्पणियों, और अपनी मूल समारोह के कोड देखने के बाद, यह संभावना है कि अपवाद उठाया है जब आप check_hardware_stuff() कहते हैं। डीबग करने के लिए यह काफी आसान है। मैं आपके फ़ंक्शन को इस तरह से बदल दूंगा:

हस्ताक्षरित चार संस्करणस्ट्रिंग [50];

__declspec(dllexport) unsigned char* Version_String() 
{ 
    strcpy(versionString, "testing"); 
    return versionString; 
} 

है कि अभी भी तो विफल रहता है मेरा अनुमान है कि त्रुटि अपने DLL के DllMain में उठाया जाता है। डीबग करें कि उपरोक्त फ़ंक्शन को एक सादे वेनिला डीएलएल में डालने से कुछ और नहीं होता है।

मूल जवाब

कॉलिंग सम्मेलन सबसे स्पष्ट समस्या है। आपका मूल कोड सबसे अधिक संभावना cdecl का उपयोग करता है लेकिन पी/invoke डिफ़ॉल्ट stdcall है। अपने पी बदलें/हस्ताक्षर आह्वान इस तरह होने के लिए:

[DllImport("BSL430.dll", CallingConvention=CallingConvention.Cdecl)] 
public extern static IntPtr Version_String(); 

आप सुरक्षित रूप से CharSet पैरामीटर छोड़ सकते हैं क्योंकि आप एक सूचक के रूप में वापसी मान इलाज कर रहे हैं के बाद से मानकों में से कोई भी पाठ है।

संपादित करें: हंस सही टिप्पणियों में बताते हैं कि चूंकि कोई पैरामीटर नहीं है, इसलिए कॉलिंग सम्मेलन गलत मिलान कोई फर्क नहीं पड़ता। तो यह समस्या नहीं है।

कॉल करें Marshal.PtrToStringAnsi एक .net स्ट्रिंग में कनवर्ट करने के लिए।

string version = Marshal.PtrToStringAnsi(Version_String()); 

PtrToStringAnsi के बाद से है कि आप पी की वापसी प्रकार के रूप में IntPtr का उपयोग एक IntPtr पैरामीटर मैं सिफारिश करेंगे उम्मीद कर रही है/हस्ताक्षर आह्वान।

यह सब मानते हैं कि आपके मूल कार्य से लौटाई गई स्मृति को मूल डीएलएल में आवंटित और मुक्त किया जाता है। यदि यह आवंटित ढेर है और आप कॉलर को इसे रद्द करने की उम्मीद करते हैं तो आपको एक छोटी सी समस्या है। आप सी # से मेमोरी को कैसे हटाते हैं क्योंकि आपके पास मूल डीएलएल के ढेर तक पहुंच नहीं है?

सरल समाधान स्मृति आवंटित करने के लिए साझा COM ढेर का उपयोग करना है। स्ट्रिंग के लिए बफर आवंटित करने के लिए CoTaskMemAlloc पर कॉल करें। फिर रिटर्न वैल्यू string के रूप में घोषित करें और पी/आवेक मार्शलर COM आवंटक के साथ विघटित हो जाएगा।

[DllImport("BSL430.dll", CallingConvention=CallingConvention.Cdecl)] 
public extern static string Version_String(); 
... 
string version = Version_String(); 
बेशक

, यह केवल लागू होता है आप लौट रहे हैं, तो ढेर आबंटित स्मृति कि आप कॉलर पुनःआवंटन की उम्मीद है।

+0

त्वरित उत्तर के लिए धन्यवाद। मैंने कोड की कोशिश की, लेकिन मुझे अभी भी वही अपवाद मिल रहा है। मुझे डीएलएल कोड पर एक नज़र आया, और जो मैं कह सकता हूं, स्ट्रिंग को विश्व स्तर पर एक निश्चित आकार सरणी के रूप में घोषित किया गया है: 'हस्ताक्षरित चार संस्करणस्ट्रिंग [50]; '। जो मुझे पता है, उससे इस मामले में और आवंटन की आवश्यकता नहीं है, है ना? – andreiscurei

+1

यह कॉलिंग कॉन्फ़्रेंस नहीं हो सकता है, फ़ंक्शन कोई तर्क नहीं लेता है। –

+0

आपको किस बिंदु पर अपवाद मिलता है? डीएलएल को कॉल करते समय, या वापस लौटने वाले मूल्य के साथ कुछ करते समय? –

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