2008-10-09 13 views
25

मैं C++ निम्नलिखित struct है:मार्शल सी ++ struct सरणी

void GetData(LPRData *data); 
: इन संरचनाओं की 3 की एक सरणी प्राप्त करने के लिए

#define MAXCHARS 15 

typedef struct 
{ 
    char data[MAXCHARS]; 
    int prob[MAXCHARS]; 
} LPRData; 

और एक समारोह है कि मैं पी रहा हूँ/में लागू

C++ में मैं बस कुछ इस तरह करना होगा:

LPRData *Results; 
Results = (LPRData *)malloc(MAXRESULTS*sizeof(LPRData)); 
GetData(Results); 

और यह सिर्फ अच्छा काम करेंगे, लेकिन सी # में मैं यह काम करने के लिए नहीं कर पा रहे। मेरे द्वारा बनाए गए इस तरह एक सी # struct:

public struct LPRData 
{ 

    /// char[15] 
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)] 
    public string data; 

    /// int[15] 
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)] 
    public int[] prob; 
} 

और अगर मैं उन लोगों में से 3 (और उनके सभी उप-सरणियों) की एक सरणी को प्रारंभ और यह इस में पारित:

GetData(LPRData[] data); 
यह

सफलता के साथ लौटता है, लेकिन एलपीआरडाटा सरणी में डेटा नहीं बदला है।

मैं भी एक कच्चे बाइट सरणी 3 LPRData के आकार बना सकते हैं और इस तरह एक समारोह प्रोटोटाइप में पारित करने के लिए है कि कोशिश की है:

GetData (बाइट [] डेटा);

लेकिन उस स्थिति में मुझे पहली एलपीआरडेटा संरचना से "डेटा" स्ट्रिंग मिल जाएगी, लेकिन इसके बाद कुछ भी नहीं, जिसमें एक ही एलपीआरडेटा से "प्रोब" सरणी शामिल है।

किसी भी विचार को ठीक से कैसे संभालना है इसका कोई विचार?

उत्तर

23

मैं अपने struct decloration करने के लिए कुछ विशेषताएं जोड़ना कोशिश करेगा

[StructLayout(LayoutKind.Sequential, Size=TotalBytesInStruct),Serializable] 
public struct LPRData 
{ 
/// char[15] 
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)] 
public string data; 

/// int[15] 
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)] 
public int[] prob; 
} 

* ध्यान दें TotalBytesInStruct एक चर

JaredPar प्रतिनिधित्व करने के लिए इरादा नहीं है भी सही है कि IntPtr वर्ग का उपयोग कर उपयोगी हो सकता है , लेकिन यह काफी समय से रहा है क्योंकि मैंने PInvoke का उपयोग किया है, इसलिए मैं जंगली हूँ।

+1

कहां जारी किया जा रहा है, मैंने इस दृष्टिकोण का उपयोग किया है, लेकिन मुझे मोनो में अपवाद मिलते हैं कि चर नल संदर्भों पर सेट हैं। उदाहरण के लिए, "prob" शून्य है इसलिए यह काम नहीं करना चाहता है। क्या मुझे किसी बिंदु पर इनका नया होना चाहिए, या क्या किसी भी तरह ढांचे द्वारा संभाला जाना चाहिए? धन्यवाद – swinefeaster

13

एक चाल जब संकेत के साथ काम कर सिर्फ एक IntPtr उपयोग करने के लिए है। इसके बाद आप अपने परिणामों को प्राप्त करने के लिए संरचना के आकार के आधार पर पॉइंटर और वृद्धि पर मार्शल.PtrToStructure का उपयोग कर सकते हैं।

static extern void GetData([Out] out IntPtr ptr); 

LPRData[] GetData() 
{ 
    IntPtr value; 
    LPRData[] array = new LPRData[3]; 
    GetData(out value); 
    for (int i = 0; i < array.Length; i++) 
    { 
     array[i] = Marshal.PtrToStructure(value, typeof(LPRData)); 
     value += Marshal.SizeOf(typeof(LPRData)); 
    } 
    return array; 
} 
+2

लाइन 11 या तो होना चाहिए: 64 + बिट चलाने पर '+ =' से '=' और 'ToInt32' से' ToInt64' बदलें; या, 'value.ToInt32()' को हटा दें? – maxwellb

+0

@ मैक्सवेल, हाँ। लिखित कोड 64 बिट सुरक्षित नहीं है। – JaredPar

+4

जो मैं वास्तव में प्राप्त कर रहा हूं, यह है कि आप पॉइंटर.toInt + sizeof (struct) की वृद्धि से वृद्धि-असाइन कर रहे हैं। क्या वृद्धि केवल आकार (संरचना) नहीं होगी? – maxwellb

2

आप OutAttribute साथ GetData पैरामीटर को चिह्नित किया था? जब सरणियों के लिए आवेदन किया और स्वरूपित, गैर blittable प्रकार

InAttribute और OutAttribute संयोजन विशेष रूप से उपयोगी है। कॉलर्स को इन प्रकारों को लागू करते समय केवल को कैली बदलते हैं, जब आप दोनों गुणों को लागू करते हैं।

2

ऐसा ही एक विषय this question पर चर्चा की गई थी, और निष्कर्ष में से एक CharSet नामित पैरामीटर CharSet.Ansi में सेट होना चाहिए था।अन्यथा, हम char सरणी के बजाय wchar_t सरणी बनायेंगे। इस प्रकार, सही कोड निम्नानुसार होगा:

[Serializable] 
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct LPRData 
{ 
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)] 
    public string data; 

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)] 
    public int[] prob; 
}