2011-07-18 13 views
11

मैं एक बोर्लैंड सी एपीआई के साथ सी # में काम कर रहा हूं जो तारों के लिए कई बाइट पॉइंटर्स का उपयोग करता है। मुझे कुछ सी # तारों को (अल्पकालिक) बाइट * के रूप में पारित करने की आवश्यकता का सामना करना पड़ा है।क्या सी # में स्थिरांक हैं?

यह मेरी प्राकृतिक धारणा होगी कि ढेर पर एक कॉन्स ऑब्जेक्ट आवंटित नहीं किया जाएगा, लेकिन सीधे प्रोग्राम मेमोरी में संग्रहीत किया जाएगा, लेकिन मैं इसे किसी दस्तावेज़ में सत्यापित करने में असमर्थ हूं।

यहां एक उदाहरण है जो मैंने लगातार स्ट्रिंग में पॉइंटर उत्पन्न करने के लिए किया है। यह परीक्षण में लक्षित के रूप में काम करता है, मुझे यकीन नहीं है कि यह वास्तव में सुरक्षित है, या यह केवल भाग्य के माध्यम से काम कर रहा है।

private const string pinnedStringGetWeight = "getWeight"; 

unsafe public static byte* ExampleReturnWeightPtr(int serial) 
{ 
    fixed (byte* pGetWeight = ASCIIEncoding.ASCII.GetBytes(pinnedStringGetWeight)) 
     return pGetWeight; 
} 

क्या यह कॉन्स्ट वास्तव में पिन किया गया है, या क्या इसे स्थानांतरित किया जा सकता है?


@Kragen:

[DllImport("sidekick.dll", CallingConvention = CallingConvention.Winapi)] 
public static extern int getValueByFunctionFromObject(int serial, int function, byte* debugCallString); 

यह वास्तविक समारोह है:

यहाँ आयात है। हाँ, यह वास्तव में एक स्थिर समारोह सूचक की आवश्यकता है:

private const int FUNC_GetWeight = 0x004243D0; 

private const string pinnedStringGetWeight = "getWeight"; 

unsafe public static int getWeight(int serial) 
{ 
    fixed (byte* pGetWeight = ASCIIEncoding.ASCII.GetBytes(pinnedStringGetWeight)) 
     return Core.getValueByFunctionFromObject(serial, FUNC_GetWeight, pGetWeight); 
} 

के बाद एक और तरीका है कि मैं जब मेरी एपीआई मजाक, एक स्थिर struct, जो मैं भी आशा व्यक्त की पिन किया गया, का उपयोग कर किया जाता है। मैं इसे सरल बनाने के लिए एक रास्ता खोजने की उम्मीद कर रहा था।

public byte* getObjVarString(int serial, byte* varName) 
{ 
    string varname = StringPointerUtils.GetAsciiString(varName); 
    string value = MockObjVarAttachments.GetString(serial, varname); 
    if (value == null) 
     return null; 
    return bytePtrFactory.MakePointerToTempString(value); 
} 

static UnsafeBytePointerFactoryStruct bytePtrFactory = new UnsafeBytePointerFactoryStruct(); 
private unsafe struct UnsafeBytePointerFactoryStruct 
{ 
    fixed byte _InvalidScriptClass[255]; 
    fixed byte _ItemNotFound[255]; 
    fixed byte _MiscBuffer[255]; 

    public byte* InvalidScriptClass 
    { 
     get 
     { 
      fixed (byte* p = _InvalidScriptClass) 
      { 
       CopyNullString(p, "Failed to get script class"); 
       return p; 
      } 
     } 
    } 

    public byte* ItemNotFound 
    { 
     get 
     { 
      fixed (byte* p = _ItemNotFound) 
      { 
       CopyNullString(p, "Item not found"); 
       return p; 
      } 
     } 
    } 

    public byte* MakePointerToTempString(string text) 
    { 
     fixed (byte* p = _ItemNotFound) 
     { 
      CopyNullString(p, text); 
      return p; 
     } 
    } 

    private static void CopyNullString(byte* ptrDest, string text) 
    { 
     byte[] textBytes = ASCIIEncoding.ASCII.GetBytes(text); 
     fixed (byte* p = textBytes) 
     { 
      int i = 0; 
      while (*(p + i) != 0 && i < 254 && i < textBytes.Length) 
      { 
       *(ptrDest + i) = *(p + i); 
       i++; 
      } 
      *(ptrDest + i) = 0; 
     } 
    } 
} 
+1

यह नहीं है मूल कोड के लिए मार्शल स्ट्रिंग्स के लिए रास्ता - क्या आप अपने सी एपीआई को (संभवतः पी/इनवोक) कॉल का एक उदाहरण पोस्ट कर सकते हैं? – Justin

+1

मुझे दृढ़ता से संदेह है कि निरंतर तार प्रभावी ढंग से "पिन" होते हैं, क्योंकि मुझे विश्वास नहीं है कि वे कूड़े से एकत्रित ढेर पर संग्रहीत हैं। इसके लिए साक्ष्य का एक टुकड़ा यह है कि विधि स्ट्रिंग के हिस्से के रूप में प्रदान की गई सतत स्ट्रिंग के साथ "एलडीस्ट्र" आईएल ओपोड का उपयोग करके निरंतर तार लोड किए जाते हैं। –

+1

मुझे अपने पिछले बयान को स्पष्ट करना चाहिए। "निश्चित कथन कचरा कलेक्टर को एक चलने योग्य चर को स्थानांतरित करने से रोकता है। निश्चित कथन केवल एक असुरक्षित संदर्भ में अनुमत है। फिक्स्ड आकार बफर बनाने के लिए भी फिक्स्ड का उपयोग किया जा सकता है।" - http://msdn.microsoft.com/en-us/library/f58wzh21(v=VS.100).aspx - RunUO इतना 2010 है :-) –

उत्तर

13

कैसे स्थिरांक आवंटित किए जाते हैं इस मामले में कोई फर्क नहीं करना चाहिए, क्योंकि ASCIIEncoding.ASCII.GetBytes() एक नया बाइट सरणी देता है (यह निरंतर के आंतरिक सरणी वापस नहीं लौट सकते, क्योंकि इसे दूसरे तरीके से एन्कोड किया गया है (संपादित करें: वहाँ उम्मीद है कि है कोई रास्ता string की आंतरिक सरणी के लिए पॉइंटर प्राप्त करने के लिए, क्योंकि स्ट्रिंग अपरिवर्तनीय हैं))। हालांकि, गारंटी है कि जीसी सरणी को छूएगी, केवल तब तक रहती है जब तक fixed गुंजाइश करता है - दूसरे शब्दों में, जब फ़ंक्शन वापस आता है, तो स्मृति अब पिन नहीं होती है।

+0

यह निश्चित रूप से मेरे प्रश्न का उत्तर देता है। पूरी तरह से इसे याद किया। बहुत बहुत धन्यवाद। मेरा लौटा बाइट * लौटने के बाद पूरी तरह से अविश्वसनीय है, मैं भाग्यशाली हो रहा हूं। – Derrick

+0

यदि यह आपके प्रश्न का उत्तर देता है, तो आपको इसे उत्तर के रूप में चिह्नित करना चाहिए। –

+0

@ जुदाह हिमांगो: मुझे यकीन नहीं है कि क्या शाब्दिक विषय प्रश्न है कि क्या पंखों को पिन किया गया है, इसका उत्तर दिया गया है, भले ही यह उत्तर मेरे कोड की शुद्धता (इन) शुद्धता के बारे में प्रश्न को पूरा करने के लिए पूरी तरह से पर्याप्त है। – Derrick

1

Kragans टिप्पणी के आधार पर, मैं उचित तरीके में मार्शल करने के लिए अपने स्ट्रिंग एक बाइट सूचक को देखा और अब पहला उदाहरण मैं अपने सवाल में इस्तेमाल के लिए निम्नलिखित का उपयोग कर रहा:

 [DllImport("sidekick.dll", CallingConvention = CallingConvention.Winapi)] 
     public static extern int getValueByFunctionFromObject(int serial, int function, [MarshalAs(UnmanagedType.LPStr)]string debugCallString); 
संबंधित मुद्दे