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