将C ++结构数组编译为C#

我在C ++中有以下结构:

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

还有一个我正在调用的函数来获得这些结构中的3个数组:

 void GetData(LPRData *data); 

在C ++中,我只是做这样的事情:

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

它会工作得很好,但在C#我似乎无法得到它的工作。 我已经创build了一个C#结构像这样:

 public struct LPRData { /// char[15] [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)] public string data; /// int[15] [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)] public int[] prob; } 

如果我初始化这些(及其所有子数组)的数组,并将其传递给它:

 GetData(LPRData[] data); 

它返回成功,但LPRData数组中的数据没有改变。

我甚至尝试创build一个大小为3 LPRData的原始字节数组,并将其传递到函数原型中,如下所示:

GetData(byte [] data);

但是在这种情况下,我将从第一个LPRData结构中获取“data”string,但是之后什么都没有,包括来自同一个LPRData的“prob”数组。

任何想法如何妥善处理这个?

我会尝试添加一些属性到你的结构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不是用来表示一个variables

JaredPar也是正确的,使用IntPtr类可能是有帮助的,但它已经相当一段时间,因为我已经使用PInvoke,所以我生锈。

处理指针时的一个窍门就是使用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; } 

PInvoke Interop Assistant可能会有所帮助。 http://clrinterop.codeplex.com/releases/view/14120

你用OutAttribute标记了GetData参数吗?

当应用于数组和格式化的不可擦除types时,组合InAttribute和OutAttribute特别有用。 只有当您应用这两个属性时,调用者才会看到被调用者对这些types所做的更改。

在这个问题上讨论了一个类似的话题,其中一个结论是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; }