2009-08-21 10 views
16

मैं निम्नलिखित सी ++ समारोह परिभाषा है, जो मैं प्रबंधित कोड से PInvoke के माध्यम से कॉल करने के लिए कोशिश कर रहा हूँ है:मार्शल SIZE_T * के लिए सही तरीका?

bool FooBar(SIZE_T* arg1); 

मेरे कामयाब घोषणा के रूप में देखा इस प्रकार है:

[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)] 
private static extern bool FooBar(ref uint arg1); 

आप में से कुछ एक ही देख सकते हैं अंततः मैंने किया बग। यह 64 बिट पोर्टेबल नहीं है। SIZE_T परिवर्तनीय आकार (32-64 बिट) का है क्योंकि यह सूचक है। प्रबंधित आकार पर पॉइंटर सही ढंग से 64 बिट तक अनुवाद करता है, लेकिन यूंट नहीं करता है, और आप arg1 के ऊपरी बिट्स में ट्रैश के साथ समाप्त हो सकते हैं। यह एक विशेष रूप से लगातार त्रुटि के बाद से कचरा अक्सर था सिर्फ शून्य :(

एकमात्र समाधान मैं काम करने के लिए मिल गया है निम्नलिखित कामयाब घोषणा है:

[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)] 
private static extern bool FooBar(ref IntPtr arg1); 

बेशक यह काम करता है क्योंकि IntPtr इसके आकार भिन्न हो सकते हैं सही ढंग से। मेरे कोड में मैं केवल इंटीपीआरटी को एक पूर्णांक के रूप में मानता हूं, और यह काम करता है, हालांकि यह बदसूरत हैक की तरह दिखता है। ऐसा लगता है कि यह ठीक से निर्दिष्ट करने का कोई तरीका होना चाहिए, शायद UnmanagedType.SysUInt का उपयोग करके, लेकिन मैं रहा हूं किसी भी अन्य कामकाजी समाधान के साथ आने में असमर्थ।

उत्तर

19

IntPtr और/याका उपयोग करना यह ठीक से कर रहा है - इस उद्देश्य के लिए विशेष रूप से प्रकार हैं! मुझे समझ में नहीं आता कि आप इसे "बदसूरत हैक" क्यों मानते हैं। मुझे यह भी यकीन नहीं है कि आपका प्रस्तावित विकल्प क्या होगा - uint पर मूल्यों को मैप करने की अनुमति देने के लिए किसी भी प्रकार की विशेषता मूल रूप से गलत होगी, क्योंकि सी # uint आर्किटेक्चर के बावजूद 32-बिट होने की गारंटी है, और इसलिए 64- बिट प्लेटफ़ॉर्म, इसे सही ढंग से मार्शल करने के लिए, इसे आधा ट्रिम करना होगा, डेटा खोना होगा, और परिणाम बेकार परिणाम देगा।

+1

मैं इसे एक बदसूरत हैक के रूप में देखता हूं क्योंकि IntPtr को किसी चीज़ के लिए सूचक का प्रतिनिधित्व करना चाहिए। हालांकि मैं इसे सीधे एक पूर्णांक के रूप में सीधे इलाज कर रहा हूं। SysUInt विशेष रूप से बताता है कि यह एक यूंट की एक चर आकार का प्रतिनिधित्व है। वास्तव में जो मैं चाहता हूं, सिवाय इसके कि मैं यह समझ नहीं पा रहा हूं कि इसे SysUInt के बजाय एक SysUInt सूचक के रूप में मूल रूप से मार्शल कैसे करें। – sooniln

+0

आप SIZE_T को एक तर्क के रूप में एक संकेतक का उपयोग कर रहे हैं, Soonil। IntPtr बहुत उपयुक्त दिखता है –

+0

आपको पता चलेगा कि मैं इंटप्राट का उपयोग नहीं कर रहा हूं, हालांकि, मैं रेफ इंटिप्ट का उपयोग कर रहा हूं। – sooniln

12

UIntPtr उपयोग करने के लिए सही प्रकार है।

size_t एक हस्ताक्षरित, सूचक आकार का पूर्णांक है और यह वही है जो UIntPtr का अर्थ है। नाम में "पीटीआर" थोड़ा उलझन में हो सकता है, मैं सहमत हूं। इसका वास्तव में मतलब नहीं है "यह एक सूचक है", इसका मतलब है "यह सूचक आकार पूर्णांक है"। तो आपकी घोषणा होगी:

[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)] 
private static extern bool FooBar(ref UIntPtr arg1); 
+0

आह बहुत अच्छी तरह से :) :) पहले बुरी तरह नामित एपीआई नहीं होगा, हे। – sooniln

+0

असल में, इस तरह के प्रकार के लिए यह एक आम नाम है। Win32 APIs typedefs 'INT_PTR' और' UINT_PTR'। और आईएसओ सी 99 में 'intptr_t' और 'uintptr_t'' ' है। इसलिए यह एक गलत नामक हो सकता है, अब तक यह एक पारंपरिक है। –

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