2008-10-09 78 views
25

我在C++下面的結構:元帥C++結構陣列到C#

#define MAXCHARS 15 

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

和一個函數,我是P /調用到獲得的這些結構的3數組:

void GetData(LPRData *data); 

在C++中我只想做這樣的事情:

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

它會工作得很好,但在C#中我似乎無法得到它的工作。 我已經創建了一個C#結構是這樣的:

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); 

它成功返回,但LPRData數組中的數據沒有改變。

我甚至試圖創建一個原始字節數組的3點LPRData的大小並傳遞到一個函數原型如下:

的GetData(字節[]數據);

但是在這種情況下,我會從第一個LPRData結構中獲取「數據」字符串,但後面什麼也沒有,包括來自同一個LPRData的「prob」數組。

如何正確處理這個問題的任何想法?

回答

23

我會嘗試加入一些屬性,你的結構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,所以我很生疏。

13

處理指針時的一個竅門就是使用IntPtr。然後,您可以在指針上使用Marshal.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 2010-07-08 19:20:03

+0

@maxwellb,是的。所寫的代碼不是64位安全的。 – JaredPar 2010-07-08 19:59:45

2

您是否標記了GetData參數OutAttribute

組合InAttribute和 OutAttribute當施加到陣列和格式化, 非Blittable型是特別有用的 。只有當您應用這兩個屬性時,呼叫者纔會看到被調用者對這些類型 所做的更改 。

2

類似的話題是關於this question討論和結論之一是,在CharSet命名參數必須設置爲CharSet.Ansi。否則,我們將製作wchar_t陣列而不是char陣列。因此,正確的代碼如下:

[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; 
}