解组包含结构的可变大小数组的结构
Unmarshaling a structure containing a variable-size array of a structure
我正在尝试解组嵌套在另一个结构中的结构的可变长度数组,如下面的代码所示:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CardInfoRequest
{
public ulong CardId;
public byte AppListLength;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct)]
public CardApp[] AppList;
}
[Serializable()]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CardApp
{
public ulong CardAppId;
public byte SomeInformation;
}
我正在解组它:
var lDataPointer = Marshal.AllocHGlobal(pSize);
Marshal.Copy(pData, 0, lDataPointer, pSize);
var lResult = Marshal.PtrToStructure(lDataPointer, typeof(CardInfoRequest));
Marshal.FreeHGlobal(lDataPointer);
其中 pData 是包含编组结构的字节数组,pSize 是它在运行时的大小(当数组有一项时为 18,当数组有两项时为 27,依此类推...)。
但是,无论流的字节大小如何,每当我解组它时,我总是得到 AppList.Length == 1。
我可以正确解组吗?我应该逐字节地做吗?
提前致谢!
pinvoke 编组器不知道它需要创建多大的数组。固定大小的缓冲区也不能工作。你必须分两步完成,首先解组前 2 个成员,你现在从 AppListLength 知道数组大小。创建数组,然后在循环中一个一个地解组数组元素。
大致如此(未经测试)
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct CardInfoRequestHeader
{
public ulong CardId;
public byte AppListLength;
}
public struct CardInfoRequest
{
public CardInfoRequestHeader Header;
public CardApp[] AppList;
}
...
var req = new CardInfoRequest();
req.Header = (CardInfoRequestHeader)Marshal.PtrToStructure(pData, typeof(CardInfoRequestHeader));
req.AppList = new CardApp(req.Header.AppListLength);
pData += Marshal.SizeOf(CardInfoRequestHeader);
for (int ix = 0; ix < req.AppList.Length; ++ix) {
req.AppList = (CardInfo)Marshal.PtrToStructure(pData, typeof(CardInfo));
pData += Marshal.SizeOf(CardInfo);
}
注意 ulong
和 Pack = 1
是危险信号,非托管数据很少像那样。代码片段确实做出了 Pack=1 是准确的硬性假设。
我正在尝试解组嵌套在另一个结构中的结构的可变长度数组,如下面的代码所示:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CardInfoRequest
{
public ulong CardId;
public byte AppListLength;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct)]
public CardApp[] AppList;
}
[Serializable()]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CardApp
{
public ulong CardAppId;
public byte SomeInformation;
}
我正在解组它:
var lDataPointer = Marshal.AllocHGlobal(pSize);
Marshal.Copy(pData, 0, lDataPointer, pSize);
var lResult = Marshal.PtrToStructure(lDataPointer, typeof(CardInfoRequest));
Marshal.FreeHGlobal(lDataPointer);
其中 pData 是包含编组结构的字节数组,pSize 是它在运行时的大小(当数组有一项时为 18,当数组有两项时为 27,依此类推...)。
但是,无论流的字节大小如何,每当我解组它时,我总是得到 AppList.Length == 1。
我可以正确解组吗?我应该逐字节地做吗?
提前致谢!
pinvoke 编组器不知道它需要创建多大的数组。固定大小的缓冲区也不能工作。你必须分两步完成,首先解组前 2 个成员,你现在从 AppListLength 知道数组大小。创建数组,然后在循环中一个一个地解组数组元素。
大致如此(未经测试)
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct CardInfoRequestHeader
{
public ulong CardId;
public byte AppListLength;
}
public struct CardInfoRequest
{
public CardInfoRequestHeader Header;
public CardApp[] AppList;
}
...
var req = new CardInfoRequest();
req.Header = (CardInfoRequestHeader)Marshal.PtrToStructure(pData, typeof(CardInfoRequestHeader));
req.AppList = new CardApp(req.Header.AppListLength);
pData += Marshal.SizeOf(CardInfoRequestHeader);
for (int ix = 0; ix < req.AppList.Length; ++ix) {
req.AppList = (CardInfo)Marshal.PtrToStructure(pData, typeof(CardInfo));
pData += Marshal.SizeOf(CardInfo);
}
注意 ulong
和 Pack = 1
是危险信号,非托管数据很少像那样。代码片段确实做出了 Pack=1 是准确的硬性假设。