2011-03-15 18 views
25

से टेक्स्ट कैसे वापस करें I मूल (सी ++) कोड और प्रबंधित (सी #) कोड के बीच इंटरऑपरेबिलिटी के लिए पिनवोक का उपयोग कर रहा हूं। मैं जो हासिल करना चाहता हूं वह मूल कोड से मेरे प्रबंधित कोड में कुछ पाठ प्राप्त करता है। इसके लिए मैं बहुत सारी चीजों को आजमाता हूं, जैसे [IN] और [आउट] का उपयोग करके स्ट्रिंग/स्ट्रिंगबिल्डर को रेफरी करके, मार्शलिंग टू एलपीस्ट्रेट, फंक्शन इत्यादि से स्ट्रिंग लौटा रहा है लेकिन मेरे मामले में कुछ भी काम नहीं करता है। कुछ छोटे कोड के साथ किसी भी मदद की अत्यधिक सराहना की जाएगी।मूल (सी ++) कोड

उत्तर

42

मैं एक BSTR साथ यह करना चाहते हैं, क्योंकि यह मतलब है कि आप दो बार स्ट्रिंग प्रति एक बार देशी में कॉल करने के लिए, एक बार लंबाई पाने के लिए और उसके बाद सामग्री प्राप्त करने के लिए नहीं है।

BSTR के साथ मार्शलर BSTR को सही मेमोरी मैनेजर के साथ हटाने की देखभाल करेगा ताकि आप सुरक्षित रूप से इसे अपने सी ++ कोड से बाहर कर सकें।

सी ++

#include <comutil.h> 
BSTR GetSomeText() 
{ 
    return ::SysAllocString(L"Greetings from the native world!"); 
} 

सी #

[DllImport(@"test.dll", CallingConvention = CallingConvention.Cdecl)] 
[return: MarshalAs(UnmanagedType.BStr)] 
private static extern string GetSomeText(); 

वहाँ BSTR में से एक नाबालिग खामी है, अर्थात् है कि यह एक UTF-16 पेलोड किया जाता है, लेकिन अपने स्रोत डेटा अच्छी तरह से char* हो सकता है ।

इस पर काबू पाने के लिए आप इस तरह BSTR को char* से रूपांतरण लपेट कर सकते हैं:

BSTR ANSItoBSTR(const char* input) 
{ 
    BSTR result = NULL; 
    int lenA = lstrlenA(input); 
    int lenW = ::MultiByteToWideChar(CP_ACP, 0, input, lenA, NULL, 0); 
    if (lenW > 0) 
    { 
     result = ::SysAllocStringLen(0, lenW); 
     ::MultiByteToWideChar(CP_ACP, 0, input, lenA, result, lenW); 
    } 
    return result; 
} 

इस तरह से बाहर सबसे मुश्किल से एक है, और अब यह अन्य रैपर जोड़ना आसान है LPWSTR से BSTR कन्वर्ट करने के लिए , std::string, std::wstring आदि

+0

@rturrado वास्तव में संपादन में आपके सुधारों के लिए बहुत धन्यवाद। –

+0

उत्तर बहुत उपयोगी है, इसलिए यह इसके लायक है। बीटीडब्ल्यू, सिर्फ यह महसूस कर रहा है कि 'अच्छी तरह से कर सकते हैं *' में 'होना' गायब है। – rturrado

+0

फ़ंक्शन को स्वचालित रूप से स्ट्रिंग की लंबाई की गणना करने के लिए 'MultiByteToWideChar'' के चौथे तर्क के रूप में आप '-1' को पारित कर सकते हैं; 'lstrlenA' को स्वयं कॉल करने की आवश्यकता से बचाता है। –

3

Here एक विषय स्ट्रिंग मार्शलिंग पर चर्चा की गई है। विशेषता के साथ पैरामीटर चिह्नित करने के लिए

यह की जरूरत

[MarshalAs(UnmanagedType.LPSTR)] 
4

यहाँ सी # के माध्यम से ऐसा करने का एक उदाहरण है। मैं मूल कार्य GetWindowText को cIn के माध्यम से cInvoking द्वारा कॉल कर रहा हूं। GetWindowText खिड़की का कैप्शन देता है जिसका handle इसे पास किया जाता है।

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); 
    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    static extern int GetWindowTextLength(IntPtr hWnd); 

    public static string GetText(IntPtr hWnd) 
    { 
     // Allocate correct string length first 
     int length = GetWindowTextLength(hWnd); 
     StringBuilder sb = new StringBuilder(length + 1); 
     GetWindowText(hWnd, sb, sb.Capacity); 
     return sb.ToString(); 
    }   

    private void button1_Click(object sender, EventArgs e) 
    { 
     string str = GetText(this.Handle); 
    } 
0

आप एक char * लौट रहे हैं, और (या आपको लगता है कि कोड को संशोधित नहीं कर सकते हैं) C/C++ अपनी वापसी मूल्य के लिए स्मृति को आबंटित करने कोड को संशोधित करने के लिए नहीं करना चाहते हैं, तो आप अपना बदल सकते हैं 0 #वापस करने के लिए सी # बाहरी फ़ंक्शन-प्रोटोटाइप, और खुद को मार्शल करें।

उदाहरण के लिए, यहाँ इंटरॉप मैं Pocketsphinx के लिए लिखा था का एक टुकड़ा है:

[DllImport("sphinxbase.dll", CallingConvention = CallingConvention.Cdecl)] 
private static extern IntPtr /* char const * */ jsgf_grammar_name(IntPtr /* jsgf_t * */ jsgf); 

और यहाँ सी # JsgfGrammar वर्ग के लिए मिल-एक्सेसर है। m_pU एक IntPtr है जो कच्चे jsgf_t ऑब्जेक्ट को इंगित करता है।

public string Name 
{ 
    get 
    { 
     IntPtr pU = jsgf_grammar_name(m_pU); 
     if (pU == IntPtr.Zero) 
      strName = null; 
     else 
      strName = Marshal.PtrToStringAnsi(pU); 
     return strName; 
    } 
} 

अन्य स्ट्रिंग प्रारूप (उदा यूनिकोड) के लिए इस उदाहरण में संशोधन करना तुच्छ होना चाहिए।

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