2009-08-24 9 views
5

मुझे तारों की एक सरणी में एक सूचक को मार्शल करने में कुछ परेशानी हो रही है। यह इस तरह से हानिरहित लग रहा है:स्ट्रिंग्स की एक सरणी के लिए मार्शलिंग पॉइंटर

typedef struct 
{ 
    char* listOfStrings[100]; 
} UnmanagedStruct; 

यह वास्तव में इस तरह एक और संरचना के भीतर एम्बेडेड है:

typedef struct 
{ 
    UnmanagedStruct umgdStruct; 
} Outerstruct; 

अप्रबंधित कोड प्रबंधित कोड में वापस कॉल करता है और स्मृति आवंटित और मूल्यों में भरा के साथ एक IntPtr के रूप में Outerstruct रिटर्न ।

प्रबंधित दुनिया:

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] 
    public string[] listOfStrings; 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct Outerstruct 
{ 
    public UnmanagedStruct ums; 
} 

public void CallbackFromUnmanagedLayer(IntPtr outerStruct) 
{ 
    Outerstruct os = Marshal.PtrToStructure(outerStruct, typeof(Outerstruct)); 
    // The above line FAILS! it throws an exception complaining it cannot marshal listOfStrings field in the inner struct and that its managed representation is incorrect! 
} 

यदि मैं सूची को बदलता हूं तो बस एक इंट्राट्रेट होने के लिए मार्शल.प्रेटोस्ट्रक्चर काम करता है लेकिन अब मैं सूची में चिपकने में असमर्थ हूं और स्ट्रिंग्स को एक-एक करके निकालने में असमर्थ हूं।

उत्तर

1

ठीक है .. मैं यह काम करने के लिए मिल गया है लगता है। सत्यापित करने के लिए

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=100)] 
    public IntPtr[] listOfStrings; 
} 

for (int i = 0; i < 100; ++i) 
{ 
    if (listOfstrings[i] != IntPtr.Zero) 
     Console.WriteLine(Marshal.PtrToStringAnsi(listOfStrings[i])); 
}  
+0

ByValArray == इन-प्लेस सरणी, LPArray == एक सरणी के लिए एक सूचक। हालांकि SizeConst को अभी भी एक एलपीएआरएआरई के साथ काम करना चाहिए, इसलिए त्रुटि जब मार्शलिंग थोड़ा अजीब था। –

+0

ओह, अगर आपके पास सार्वजनिक स्ट्रिंग [] listOfStrings है, तो यह भी काम करना चाहिए, यह ByValArray है जो मुझे विश्वास में अंतर बनाता है। –

4

किसी भी मूलभूत स्ट्रिंग के अलावा कुछ भी मार्शलिंग जटिल है और पक्ष के मामलों से भरा है जो स्पॉट करना मुश्किल है। संरचना परिभाषा में सुरक्षित/सरल मार्ग के साथ जाना आमतौर पर सबसे अच्छा होता है और थोड़ी सी चीजों को साफ करने के लिए कुछ रैपर गुण जोड़ते हैं।

इस मामले मैं IntPtr की सरणी के साथ जाना होगा और फिर एक आवरण संपत्ति है कि धर्मान्तरित जोड़ने में उन्हें तार

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] 
    public IntPtr[] listOfStrings; 

    public IEnumerable<string> Strings { get { 
     return listOfStrings.Select(x =>Marshal.PtrToStringAnsi(x)); 
    } 
} 
+0

जारेड धन्यवाद: यह रूप में IntPtr []

यह काम करने लगता है मार्शल किया जाना चाहिए! मैंने अभी आपके देखने से पहले अपने ही प्रश्न का उत्तर पोस्ट किया। एक प्रश्न - मैं अपने कोड को पदों में कैसे प्रारूपित करूं? वे सभी गड़बड़ लग रहे थे और किसी को हर समय इसे संपादित और सही करना होगा। – Dilip

+0

@ डिलिप, अपना कोड स्निपेट चुनें और CTRL + K दबाएं। यह सब कुछ इंडेंट करके प्रारूपण को ठीक करेगा 4 spcaes – JaredPar

+0

@ जेरेड: बस एक त्वरित अनुवर्ती। यदि मैं UnmanagedType.LPArray का उपयोग करता हूं तो कोड बम जारी रहता है। केवल UnmanagedType.ByValArray काम करता है। अब मैं समझता हूं कि KeeperOfTheoul उसकी टिप्पणियों में क्या संकेत दे रहा था। – Dilip