2011-01-02 12 views
14

के उपयोग के बीच अंतर को समझना मुझे यह कहकर शुरू करना है कि मैंने देखा है और निश्चित {}, मार्शल.एलोक एचजीएलबल() और जीसीएचंडल के उपयोग के विवरण पाए हैं इस मंच पर और वेब पर कई लिंक में। Alloc()। हालांकि, मुझे अभी तक मार्शल क्लास बनाम जीसीएचंडल क्लास (फिक्स्ड {} के बिना और बिना) का उपयोग करने के बारे में एक संक्षिप्त स्पष्टीकरण मिल गया है।फिक्स्ड {}, मार्शल.एलोक एचजीएलबल() और जीसीएचंडल.एलोक()

मैं एक तृतीय पक्ष .NET लाइब्रेरी का उपयोग कर रहा हूं जिसमें एक "बफर" कक्षा में रीडलाइन() नामक विधि है। मैनुअल निम्नलिखित फ़ंक्शन प्रोटोटाइप दिखाता है:

बूल रीडलाइन (int x1, int y1, int x2, int y2, system.IntPtr bufData, int numRead बाहर);

bufData का एक विवरण है कि कहते हैं के साथ

: ... स्मृति क्षेत्र लाइन की लंबाई बार BytesPerPixel संपत्ति के द्वारा दिए गए मान के लिए की तुलना में बड़ा या बराबर बाइट की संख्या होनी चाहिए।

अब बाद में उपयोगकर्ता के मैनुअल में वे करते हैं बफर (जो मैं अपने विशिष्ट उदाहरण के लिए एक छोटा सा बदलाव किया है) तक पहुँचने का एक उदाहरण देता हूँ:

// Create an array large enough to hold one line from buffer 
int size = 640; 
byte[] dataLine = new byte[size * 2]; // 2 bytes per pixel 

// Pin the array to avoid Garbage collector moving it 
GCHandle dataLineHandle = GCHandle.Alloc(dataLine, GCHandleType.Pinned); 
IntPtr dataLineAddress = dataLineHandle.AddrOfPinnedObject(); 

और मैं ऊपर का पालन कर सकता है "उदाहरण के" कोड के साथ:

// Read one line of buffer data 
success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead); 

// Unpin the array 
dataLineHandle.Free() 

कि कहानी का अंत हो सकता है (और मैं अभी तक ऊपर कोड का परीक्षण करने के लिए है), लेकिन मुझे GCHandle वर्ग जो मुझे नीचे कर दिया नेट की राह googling समाप्त हो गया interoperab बड़प्पन, PInvoke, आदि

तो मेरे सवालों का ... 1) मैं का उपयोग क्यों नहीं कर सकते:

IntPtr dataLineAddress = Marshal.AllocHGlobal(size * 2); 

और (पारित कि ReadLine में)?

2) मैं भी निम्नलिखित स्निपेट (वेब ​​पर निकाला जाता है और उदाहरण से बदलाव) का उपयोग कर सकते हैं:

int size = 640; 
byte[] dataLine= new byte[size * 2]; // 2 bytes per pixel 

// prevent garbage collector from moving buffer around in memory 
fixed (byte* fixedDataLine = dataLine) 
{ 
    // get IntPtr representing address of first buffer element 
    IntPtr dataLineAddress= Marshal.UnsafeAddrOfPinnedArrayElement(fixedDataLine , 0); 
    success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead); 
} 

मैं किसी में रुचि होगी ऊपर तकनीकों पर प्रकाश डाला और बाहर बिंदु कर सकते हैं कार्यान्वयन में मेरी त्रुटियों के साथ-साथ उपरोक्त विधियों के उचित होने पर इंगित करें। अंत में, भले ही उपर्युक्त विधियां सभी मान्य हों, क्या पिछले कुछ वर्षों में एक दृष्टिकोण या दूसरे की ओर एक सामान्य धक्का है?

अग्रिम धन्यवाद !! हाइप

+0

यह एक भयानक एपीआई की तरह लगता है। – SLaks

उत्तर

2

ठीक है, विकल्प भी काम करेगा। लेकिन मार्शल। AllocHGlobal नमूना पूरा नहीं हुआ है, अब आप अप्रबंधित स्मृति में डेटा मिला है। आपको अभी भी एक प्रबंधित ऑब्जेक्ट (सरणी) में लाने के लिए काम करने की आवश्यकता है ताकि आप इसे आसानी से एक्सेस कर सकें, आपको मार्शल.कॉपी() को कॉल करना होगा। अक्षम होने के बाद से डेटा दो बार कॉपी करता है। और मार्शल को कॉल करना न भूलें। फ्रीहग्लोबबल()।

निश्चित नमूना विक्रेता नमूना के समान ही करता है, यह स्पष्ट रूप से स्मृति को पिन करता है। यहां अजीबता यह है कि एपीआई एक इंटिप्ट लेता है, बाइट * नहीं। और आपको असुरक्षित कीवर्ड की अनुमति देने के लिए संकलन सेटिंग्स को बदलना होगा। यह अन्यथा अधिक कुशल नहीं है।

आप इसे अलग करके आगे नहीं हैं।

+0

हंस - अगर मेरे पास एक अप्रबंधित डीएलएल फ़ंक्शन था जिसे मैं कॉल कर रहा था जिसके लिए एक बाइट पॉइंटर को मेमोरी ब्लॉक में "भरना" चाहिए, तो "मार्शल" बनाम "जीसीएचंडल" का उपयोग करने पर प्राथमिकता है? उपरोक्त आपके उत्तर के लिए धन्यवाद। – Hyped

+0

@ हाइप - आपकी वरीयता * हमेशा * पी/Invoc marshaller इसे करने के लिए होना चाहिए। यह लगभग हमेशा संभव है। आप तर्क को अपने उदाहरण में एक सरणी के रूप में घोषित करेंगे। बाइट [] या पिक्सेलडाटा [] की तरह जहां पिक्सेलडाटा दो बाइट सदस्यों के साथ एक संरचना है। –

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