2008-12-15 15 views
41

देता है मैं कुछ सी # कोड लिखने की कोशिश कर रहा हूं जो एक अप्रबंधित DLL से एक विधि को कॉल करता है। dll में समारोह के लिए प्रोटोटाइप है:सी फ़ंक्शन के लिए PInvoke जो char *

extern "C" __declspec(dllexport) char *foo(void); 

सी # में, मैं पहली बार प्रयोग किया है:

[DllImport(_dllLocation)] 
public static extern string foo(); 

यह सतह पर काम करने के लिए लगता है, लेकिन मैं रनटाइम के दौरान स्मृति भ्रष्टाचार त्रुटियों हो रही है। मुझे लगता है कि मैं स्मृति को इंगित कर रहा हूं जो सही होता है, लेकिन पहले से ही मुक्त हो चुका है।

मैंने "पी/इनवोक इंटरऑप सहायक" नामक एक पीएनवोक कोड जेन उपयोगिता का उपयोग करने का प्रयास किया। इसने मुझे आउटपुट दिया:

[System.Runtime.InteropServices.DLLImportAttribute(_dllLocation, EntryPoint = "foo")] 
public static extern System.IntPtr foo(); 

क्या यह सही है? यदि हां, तो मैं इस IntPtr को C# में स्ट्रिंग में कैसे परिवर्तित करूं?

उत्तर

67

आपको इसे एक इंटिप्रेट के रूप में वापस करना होगा। एक सिस्टम लौट रहा है। एक PInvoke फ़ंक्शन से स्ट्रिंग प्रकार की बहुत अच्छी देखभाल की आवश्यकता है। सीएलआर को स्मृति को देशी प्रतिनिधित्व से प्रबंधित व्यक्ति में स्थानांतरित करना होगा। यह एक आसान और अनुमानित ऑपरेशन है।

हालांकि समस्या यह है कि foo() से लौटाई गई मूल स्मृति के साथ क्या करना है। CLR एक PInvoke समारोह जो सीधे स्ट्रिंग प्रकार

  1. देशी स्मृति

इसलिए यह मार्शल होगा मुक्त होने के

  • देशी स्मृति CoTaskMemAlloc साथ आवंटित किया गया था की जरूरत है देता है के बारे में निम्नलिखित दो आइटम मान लिया गया है स्ट्रिंग और फिर देशी मेमोरी ब्लॉब पर CoTaskMemFree को कॉल करें। जब तक आप वास्तव में CoTaskMemAlloc के साथ इस मेमोरी को आवंटित नहीं करते हैं, तो यह आपके एप्लिकेशन में क्रैश का सबसे अच्छा कारण होगा।

    आदेश यहाँ सही अर्थ विज्ञान प्राप्त करने के लिए आप एक IntPtr सीधे वापस चाहिए। फिर प्रबंधित स्ट्रिंग मान प्राप्त करने के लिए मार्शल.PtrToString * का उपयोग करें। आपको अभी भी मूल स्मृति मुक्त करने की आवश्यकता हो सकती है लेकिन यह foo के कार्यान्वयन पर निर्भर करेगा।

  • 19

    आप मार्शल.PtrToStringAuto विधि का उपयोग कर सकते हैं।

    IntPtr ptr = foo(); 
    string str = Marshal.PtrToStringAuto(ptr); 
    
    +1

    यह मेरे लिए काम किया। मुझे केवल एक ही परिवर्तन 'PtrToStringAuto'' PtrToStringAnsi 'करना था अन्यथा मुझे कुछ चीनी वर्ण मिल गए – 3vts

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