2009-01-30 6 views
11

मेरे पास यह सी ++ कोड है:क्या मुझे अप्रबंधित कोड में मार्शल.PtrToStructure के माध्यम से marshaled संरचनाओं को हटाने की जरूरत है?

extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo) 
{ 
    *foo = new MY_DATA_STRUCTURE; 

    //do stuff to foo 
} 

फिर सी # में मैं इस प्रकार फ़ंक्शन को कॉल करता हूं:

[DllImport("MyDll.dll")] 
static extern void AllocateFoo(out IntPtr pMyDataStruct); 

... 

MyDataStructure GetMyDataStructure() 
{ 
    IntPtr pData; 
    ManagedAllocateFooDelegate(out pData); 

    MyDataStructure foo = (MyDataStructure)Marshal.PtrToStructure(pData, typeof(MyDataStructure)); 
    return foo; 
} 

जहां MyDataStructure एक संरचना (कक्षा नहीं) है जो MY_DATA_STRUCTURE से मेल खाती है और सदस्यों को उचित तरीके से मार्शल किया जाता है।

तो प्रश्न: क्या मुझे पीडीटा को स्टोर करने की आवश्यकता है और फिर इसे फिर से अप्रबंधित कोड में रिलीज़ करें जब MyDataStructure GC'd है? एमएसडीएन मार्शल .PtrToStructure (IntPtr, टाइप) के लिए कहता है: "मार्शल डेटा को स्मृति के एक अप्रबंधित ब्लॉक से निर्दिष्ट प्रकार के एक नए आवंटित प्रबंधित ऑब्जेक्ट में डेटा।" उस वाक्य में "मार्शल" का अर्थ "प्रतिलिपि" है? इस मामले में मुझे (IntPtr pData) को संरक्षित करने की आवश्यकता होगी और फिर इसे अप्रबंधित कोड (MyDataStructure destructor में) पास कर दें ताकि मैं एक C++ "हटाएं" कर सकूं?

मैंने खोजा है लेकिन मैं इसके लिए पर्याप्त स्पष्ट उत्तर नहीं ढूंढ सकता।

+0

आपका अप्रबंधित फ़ंक्शन, AllocateFoo, लिखित के रूप में काम नहीं करता है। पॉइंटर को वापस कॉलर पर वापस करने के लिए आपको एक अतिरिक्त स्तर की संकेत की आवश्यकता है। i.e., AllocateFoo (MY_DATA_STRUCTURE * * foo) { * foo = new MY_DATA_STRUCTURE; } – GBegen

+0

हाँ आप सही हैं! मेरा वास्तविक कोड PMY_DATA_STRUCTURE * का उपयोग करता है, मैं पोस्ट संपादित करूंगा। – Serguei

उत्तर

10

जैसा कि एरिक ने कहा, मार्शल का मतलब प्रतिलिपि है, लेकिन मुझे नहीं लगता कि उसने आपके प्रश्न के मुख्य बिंदु का उत्तर दिया है।

क्या आपको पीडीटा देशी पॉइंटर पर पकड़ने की आवश्यकता है जब तक कि MyDataStructure GCed न हो? सं।

एक बार मार्शल हो जाने पर, आपके माइडाटास्ट्रक्चर इंस्टेंस, foo में पीडीएटी द्वारा निर्देशित संरचना की एक प्रति शामिल है। आपको अब पीडीएटा पर पकड़ने की आवश्यकता नहीं है। मेमोरी रिसाव से बचने के लिए, आपको उस पीडीएटा को किसी अन्य अप्रबंधित फ़ंक्शन में पास करना होगा जो इसे हटा देगा, और यह मार्शलिंग के ठीक बाद किया जा सकता है, भले ही आप MyDataStructure इंस्टेंस पर कितना समय लगे।

7

हां, इस मामले में, मार्शल का मतलब प्रतिलिपि है; इस प्रकार, आपको अप्रबंधित कोड में अपनी याददाश्त को हटाना होगा। PtrToStructure के लिए सभी कॉल को पीडीटा द्वारा इंगित स्मृति स्थान से गंतव्य संरचना 'MyDataStructure' के आकार से संकेतित कई बाइट्स पढ़ा जाता है।

पाठ्यक्रम का विवरण बिल्कुल 'माईडाटा संरचना' जैसा दिखता है (क्या आप MyDataStructure में किसी फील्डऑफसेट या स्ट्रक्चरलाइट विशेषता का उपयोग करते हैं) - लेकिन अंतिम परिणाम यह है कि PtrToStructure से वापसी डेटा की एक प्रति है।

his answer में बताए गए, मैंने आपके प्रश्न के मुख्य बिंदु का उत्तर नहीं दिया। हां, आपको अप्रबंधित कोड में अपनी संरचना की अप्रबंधित प्रति को हटाना होगा, लेकिन नहीं, आपको पीडीएटी पर पकड़ने की आवश्यकता नहीं है - जैसे ही आप PtrToStructure को कॉल पूरा करते हैं, आप अप्रबंधित प्रति को हटा सकते हैं।

पीएस: मैंने इस पोस्ट को शामिल करने के लिए अपनी पोस्ट संपादित की है ताकि एक पोस्ट में जवाबों को समेकित किया जा सके - अगर कोई इस उत्तर को ऊपर उठाता है, तो कृपया उसके योगदान के लिए जीबीजेन के उत्तर को ऊपर उठाएं।

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