2012-03-16 13 views
19

मैं एक इंटिप्टर पॉइंटर से डेटा बाइट सरणी में प्राप्त करना चाहता हूं। मैं इसे करने के लिए निम्न कोड का उपयोग कर सकता हूं:इंटेल को मार्शल के बिना बाइट सरणी में डाला जा सकता है। कॉपी?

IntPtr intPtr = GetBuff(); 
byte[] b = new byte[length]; 
Marshal.Copy(intPtr, b, 0, length); 

लेकिन उपरोक्त कोड IntPtr से बाइट सरणी में एक कॉपी ऑपरेशन को मजबूर करता है। प्रश्न में डेटा बड़ा होने पर यह एक अच्छा समाधान नहीं है।

क्या एक बाइट सरणी में IntPtr डालने का कोई तरीका है? उदाहरण के लिए, निम्न कार्य होगा:

byte[] b = (byte[])intPtr

यह प्रतिलिपि आपरेशन की आवश्यकता को समाप्त होगा।

इसके अलावा: हम IntPtr द्वारा इंगित डेटा की लंबाई निर्धारित कैसे कर सकते हैं?

+1

आपको निश्चित रूप से डेटा कॉपी करना चाहिए क्योंकि 'IntPtr' * अप्रबंधित स्मृति * में इंगित करता है! – Yahia

+3

आपके बहुत तेज़ उत्तर के लिए धन्यवाद, लेकिन IntPtr को C++ निर्यात फ़ंक्शन से वापस कर दिया गया था, इसलिए मैं इसे कहीं भी प्रबंधित और हटा सकता हूं। मैं डेटा कॉपी नहीं करना चाहता क्योंकि डेटा वीडियो बफर है, इसलिए यह बहुत बड़ा है। प्रतिलिपि खराब प्रदर्शन करेगी। धन्यवाद! – TTGroup

+1

असुरक्षित प्रथाओं के लिए वास्तव में जाने का कोई कारण नहीं है ... आपको वास्तव में सामग्री की प्रतिलिपि बनाना चाहिए - ऐसा करने के लिए कई सुरक्षित तरीके हैं (कुछ दूसरों की तुलना में तेज़) ... – Yahia

उत्तर

17

जैसा कि अन्य ने उल्लेख किया है, प्रबंधितbyte[] में प्रतिलिपि किए बिना डेटा को स्टोर करने के लिए कोई तरीका नहीं है (आपके द्वारा प्रदान की गई वर्तमान संरचना के साथ *)। हालांकि, यदि आप वास्तव में को की आवश्यकता नहीं है तो यह एक प्रबंधित बफर में हो, आप unsafe ऑपरेशंस का उपयोग सीधे अप्रबंधित स्मृति के साथ काम करने के लिए कर सकते हैं। यह वास्तव में निर्भर करता है कि आपको इसके साथ क्या करने की ज़रूरत है।

सभी byte[] और अन्य संदर्भ प्रकार सीएलआर कचरा कलेक्टर द्वारा प्रबंधित किए जाते हैं, और यह अब उपयोग नहीं होने पर स्मृति और डिलोकेशन के आवंटन के लिए ज़िम्मेदार है। GetBuffer की वापसी से इंगित स्मृति, सी ++ कोड द्वारा आवंटित अप्रबंधित स्मृति का एक ब्लॉक है और (स्मृति मेमोरी/कार्यान्वयन विवरण अलग-अलग) अनिवार्य रूप से आपकी जीसी प्रबंधित स्मृति से अलग है। इसलिए, यदि आप जीसी प्रबंधित सीएलआर प्रकार (byte[]) का उपयोग करना चाहते हैं, तो वर्तमान में आपके अप्रबंधित स्मृति के भीतर आपके द्वारा बनाए गए सभी डेटा को आपके IntPtr पर इंगित किया गया है, तो इसे जीसी के बारे में पता चलने वाली स्मृति में स्थानांतरित (प्रतिलिपि) की आवश्यकता है। यह Marshal.Copy द्वारा या unsafe कोड या पिनवोक या आपके पास क्या है, एक कस्टम विधि द्वारा किया जा सकता है।

हालांकि, यह निर्भर करता है कि आप इसके साथ क्या करना चाहते हैं। आपने इसका वीडियो डेटा उल्लेख किया है। यदि आप डेटा में कुछ ट्रांसफॉर्म या फ़िल्टर लागू करना चाहते हैं, तो आप शायद इसे सीधे अप्रबंधित बफर पर कर सकते हैं। यदि आप बफर को डिस्क पर सहेजना चाहते हैं, तो आप शायद इसे सीधे अप्रबंधित बफर पर कर सकते हैं।

लंबाई के विषय पर, एक अप्रबंधित मेमोरी बफर की लंबाई जानने का कोई तरीका नहीं है जब तक कि बफर आवंटित फ़ंक्शन आपको यह भी बताता है कि लंबाई क्या है। यह कई तरीकों से किया जा सकता है, क्योंकि टिप्पणीकारों ने उल्लेख किया है (संरचना का पहला क्षेत्र, विधि पर paramtere बाहर)।

* अंत में, यदि आपके पास सी ++ कोड का नियंत्रण है तो इसे संशोधित करना संभव हो सकता है ताकि यह बफर आवंटित करने के लिए ज़िम्मेदार न हो, यह डेटा लिखता है, और इसके बजाय एक प्रीफरोकेटेड बफर को पॉइंटर प्रदान किया जाता है। इसके बाद आप प्रबंधितbyte[] सी # में बना सकते हैं, जो आपके सी ++ कोड द्वारा आवश्यक आकार के लिए आवंटित है, और इसे पिन करने के लिए GCHandle प्रकार का उपयोग करें और अपने सी ++ कोड को पॉइंटर प्रदान करें।

+0

आपके विस्तार स्पष्टीकरण के लिए धन्यवाद, मैंने इसे करने के लिए असुरक्षित कोड का उपयोग किया है :) – TTGroup

2

आपके पास एक प्रबंधित सरणी अप्रबंधित स्मृति पर कब्जा नहीं कर सकता है। आप या तो अप्रबंधित डेटा को एक समय में एक खंड में कॉपी कर सकते हैं, और प्रत्येक खंड को संसाधित कर सकते हैं, या UnmanagedArray कक्षा बना सकते हैं जो IntPtr लेता है और एक इंडेक्सर प्रदान करता है जो अभी भी मार्शल का उपयोग करेगा। डेटा तक पहुंचने के लिए कॉपी करें।

जैसा कि @ विनोद ने बताया है, आप इसे unsafe कोड के साथ कर सकते हैं। यह आपको सी-जैसे पॉइंटर्स का उपयोग करके सीधे मेमोरी तक पहुंचने की अनुमति देगा। हालांकि, किसी भी असुरक्षित .NET विधि को कॉल करने से पहले आपको डेटा को प्रबंधित स्मृति में मार्शल करना होगा, इसलिए आप अपने स्वयं के सी-जैसे कोड तक सीमित हैं। मुझे नहीं लगता कि आपको इससे परेशान होना चाहिए, बस सी ++ में कोड लिखें।

+0

"असुरक्षित" सामान के साथ भी नहीं? –

+0

आह, असुरक्षित सामान। हाँ, आप असुरक्षित सामान के साथ ऐसा कर सकते हैं। क्या आप वास्तव में असुरक्षित सामान चाहते हैं? – zmbq

+0

यकीन नहीं है, मेरा प्रश्न नहीं :) लेकिन यह देखना दिलचस्प होगा कि यह * कैसे किया जा सकता है, भले ही बड़ी चेतावनी झंडे हों। –

8

इस प्रयास करें:

byte* b = (byte*)intPtr; 

आवश्यक है unsafe (फ़ंक्शन हस्ताक्षर, ब्लॉक, या संकलक झंडा /unsafe में)।

+5

आपको इसका उल्लेख करना चाहिए कि इसमें फ़ंक्शन हस्ताक्षर में या घुंघराले ब्रेसिज़ की एक जोड़ी के भीतर 'असुरक्षित' कीवर्ड की आवश्यकता है: 'usafe {...} ' –

+0

धन्यवाद, मैंने अभी कोशिश की है। लेकिन जब "पॉइंटर्स और निश्चित आकार बफर" का निर्माण केवल असुरक्षित संदर्भ में किया जा सकता है तो संकलक ने त्रुटि को फेंक दिया "। मुझे यह त्रुटि समझ में नहीं आ रही है, कृपया मुझे समझाएं। धन्यवाद! – TTGroup

+2

असुरक्षित कोड की अनुमति देने के लिए आपके प्रोजेक्ट को कॉन्फ़िगर करने की आवश्यकता है, उत्तर में दिए गए कोड को असुरक्षित में लपेटने की आवश्यकता है (जैसा कि @ माइकबेंटगेई ने कहा था), और सबसे महत्वपूर्ण बात यह है कि यह आपको अप्रबंधित स्मृति के लिए एक अप्रबंधित सूचक प्रदान करता है, सीएलआर नहीं बाइट [] संदर्भ – jeffora

1

अप्रबंधित सरणी के साथ काम करने के समाधान के लिए यह Code Project पृष्ठ देखें।

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