对包含结构的可变大小数组的结构进行反编组

本文关键字:结构 数组 包含 小数 | 更新日期: 2023-09-27 18:14:50

我试图解组一个嵌套在另一个结构中的可变长度数组,如下面的代码所示:

[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。长度== 1。

我可以正确地解除编组吗?我应该一个字节一个字节地做吗?

提前感谢!

对包含结构的可变大小数组的结构进行反编组

pinvoke编组程序不知道需要创建多大的数组。固定大小的缓冲区也不能工作。您必须分两步完成,首先对前两个成员进行反编组,现在您知道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);
}

注意ulongPack = 1是危险信号,非托管数据很少看起来像那样。该代码片段确实做出了一个艰难的假设,即Pack=1是准确的。