2008-10-09 93 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; 
}