2011-02-24 6 views
5

पर जाने के लिए सी # में मार्शल संग्रह कैसे करें I एंटरप्राइज़ एप्लिकेशन डेवलपमेंट पर काम कर रहा हूं। पूरे एप्लिकेशन को सी ++ में विकसित किया गया है, यूआई को छोड़कर, जिसे सी # में विकसित किया गया है, अब सीआई ++ कोड के साथ यूआई को हुक अप करने का समय है। विस्तृत अध्ययन के बाद मैं ऐसा करने के लिए PInvoke चुनता हूं। सभी सफल हैं, एकमात्र मामला जहां मैं अटक गया हूं कि मैं सी ++ कोड में संग्रह कैसे पास कर सकता हूं। जैसे:देशी (सी ++) कोड

सी # साइड कोड

List<string> lst = new List<string>(); 
lst.Add("1"); 
lst.Add("2"); 
lst.Add("3"); 
lst.Add("4"); 

सी ++ साइड कोड

std::vector<std::string> vStr; 

अब कैसे

उत्तर

3

mzabsky उल्लेख किया है, आप इन प्रकार के मार्शल नहीं कर सकते। हालांकि, आप एक सरणी मार्शल कर सकते हैं:

सैद्धांतिक सी ++ निर्यात:

extern "C" __declspec(dllexport) void __stdcall Foo(wchar_t const* const* values, int length) 
{ 
    // Check argument validity... 

    // If you really need a vector 
    std::vector<std::wstring> vStr(values, values + length); 

    //... 
}

पी/आह्वान हस्ताक्षर:

[DllImport("foo.dll")] 
static extern void Foo([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)] string[] values, int length);

सी # से कॉल:

Foo(lst.ToArray(), lst.Count);

ध्यान दें कि मैं यहां std :: wstring का उपयोग कर रहा हूँ; आप इसके बजाए wchar_t के बजाय char का उपयोग कर सकते हैं, LPWStr के बजाय LPStr, और std :: wstring के बजाय std :: string।

ध्यान दें कि यह सूची से एक सरणी आवंटित करेगा और फिर वेक्टर सरणी की सामग्री कॉपी करेगा। यदि मूल सूची आकार में छोटा है, तो यह नगण्य चिंता का होना चाहिए।

संपादित करें: मार्कअप को ठीक करना (लेफ्टिनेंट और & gt;)।

1

आप ऐसा नहीं कर सकते ++ कोड मैं देशी सेल्सियस तक lst पारित करते हैं, केवल सी प्रकार marshalled किया जा सकता है। आपको एक सी ++/सीएलआई रैपर (या सी ++ वेक्टर के चारों ओर एक सी रैपर) लिखना होगा।

See this answer.

0

हां। आप ऐसा कर सकते हैं। दरअसल, न केवल std::string, std::wstring, किसी भी मानक सी ++ वर्ग या आपके स्वयं के वर्गों को मार्शल या तत्काल किया जा सकता है और सी #/.NET से बुलाया जा सकता है।

रैपिंग एक std::vector<any_type> सी में # वास्तव में बस नियमित पी/आह्वान इंटरॉप, यह हालांकि जटिल है साथ संभव है। किसी भी प्रकार का std::map भी सी #/.NET में किया जा सकता है।

.NET दुनिया से सी ++ ऑब्जेक्ट को तुरंत चालू करने का मूल विचार .NET से C++ ऑब्जेक्ट का सटीक आकार आवंटित करना है, फिर ऑब्जेक्ट को प्रारंभ करने के लिए C++ DLL से निर्यात किए गए कन्स्ट्रक्टर को कॉल करें, फिर आप सक्षम होंगे उस सी ++ ऑब्जेक्ट तक पहुंचने के लिए किसी भी फ़ंक्शन को कॉल करने के लिए, यदि किसी भी विधि में अन्य सी ++ कक्षाएं शामिल हैं, तो आपको उन्हें सी # कक्षा में भी लपेटने की आवश्यकता होगी, आदिम प्रकारों के तरीकों के लिए, आप बस उन्हें पी/इन्हें आमंत्रित कर सकते हैं। यदि आपके पास कॉल करने के लिए केवल कुछ विधियां हैं, तो यह आसान होगा, मैन्युअल कोडिंग में अधिक समय नहीं लगेगा। जब आप C++ ऑब्जेक्ट के साथ होते हैं, तो आप C++ ऑब्जेक्ट की विध्वंसक विधि को कॉल करते हैं, जो एक निर्यात फ़ंक्शन भी है। यदि उसके पास कोई नहीं है, तो आपको बस अपनी स्मृति को .NET से मुक्त करने की आवश्यकता है।

यहाँ एक उदाहरण है।

public class SampleClass : IDisposable 
{  
    [DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi,   CallingConvention=CallingConvention.ThisCall)] 
    public extern static void SampleClassConstructor(IntPtr thisObject); 

    [DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi,  CallingConvention=CallingConvention.ThisCall)] 
    public extern static void DoSomething(IntPtr thisObject); 

    [DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi,  CallingConvention=CallingConvention.ThisCall)] 
    public extern static void DoSomething(IntPtr thisObject, int x); 

    IntPtr ptr; 

    public SampleClass(int sizeOfYourCppClass) 
    { 
     this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass); 
     SampleClassConstructor(this.ptr); 
    } 

    public void DoSomething() 
    { 
     DoSomething(this.ptr); 
    } 

    public void DoSomethingElse(int x) 
    { 
     DoSomethingElse(this.ptr, x); 
    } 

    public void Dispose() 
    { 
     Marshal.FreeHGlobal(this.ptr); 
    } 
} 

विस्तार के लिए, कृपया नीचे दिए गए लिंक देखते हैं,

C#/.NET PInvoke Interop SDK

+0

बारे में खेद (मैं एसडीके उपकरण के लेखक हूँ)। मैं अपना जवाब बदल दूंगा। कृपया सही उत्तर मत छोड़ो। – xInterop

+0

कोई समस्या नहीं है। मैं उन सभी को बदल दूंगा। धन्यवाद! – xInterop

+0

आपके सभी उत्तरों के अपडेट के लिए धन्यवाद! – Jesse