编组c#结构

本文关键字:结构 编组 | 更新日期: 2023-09-27 18:15:58

我正在尝试序列化以下c#结构:

[Serializable]
[StructLayout(LayoutKind.Sequential, Size = 70, CharSet = CharSet.Ansi)]
public struct USSDContinueModel
{
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Length;
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_ID;
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Status;
    [MarshalAs(UnmanagedType.U4)]
    public uint Sender_ID;
    [MarshalAs(UnmanagedType.U4)]
    public uint Receiver_ID;
    [MarshalAs(UnmanagedType.U1)]
    public uint Ussd_Version;
    [MarshalAs(UnmanagedType.U1)]
    public uint Ussd_Op_Type;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string MsIsdn;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string Service_Code;
    [MarshalAs(UnmanagedType.U1)]
    public uint Code_Scheme;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 182)]
    public string Ussd_Content;
    // Calling this method will return a byte array with the contents
    // of the struct ready to be sent via the tcp socket.
    public byte[] Serialize()
    {
        // allocate a byte array for the struct data
        var buffer = new byte[Marshal.SizeOf(typeof(USSDContinueModel))];
        // Allocate a GCHandle and get the array pointer
        var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        var pBuffer = gch.AddrOfPinnedObject();
        // copy data from struct to array and unpin the gc pointer
        Marshal.StructureToPtr(this, pBuffer, false);
        gch.Free();
        return buffer;
    }
    // this method will deserialize a byte array into the struct.
    public void Deserialize(ref byte[] data)
    {
        var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
        this = (USSDContinueModel)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(USSDContinueModel));
        gch.Free();
    }
}

当我试图序列化一个结构体的实例时说:

        public USSDContinueModel continueModel;
        continueModel.Command_Length = 174;
        continueModel.Command_ID = 0x00000070;
        continueModel.Command_Status = 0;
        continueModel.Sender_ID = 0x01000005;
        continueModel.Receiver_ID = 0x2900AB12;
        continueModel.Ussd_Version = 0x20;
        continueModel.Ussd_Op_Type = 0x01;
        continueModel.MsIsdn = "08098765476";
        continueModel.Service_Code = "*308";
        continueModel.Code_Scheme = 0x44;
        continueModel.Ussd_Content = "1. Continue if you are 18+ 2. Exit i";

我一直得到错误"Type: USSDcontinueModel不能被编组为非托管结构;无法计算有意义的大小或偏移量"。

我注意到当我设置Ussd_Version, Ussd_Op_Type和Code_Scheme为[MarshalAs(UnmanagedType.U1)]时发生这种情况,但它与[MarshalAs(UnmanagedType.U4)]一起工作很好。

[MarshalAs(UnmanagedType.U1)] unmarshallable?我该怎么办?

编组c#结构

问题是定义:

[MarshalAs(UnmanagedType.U1)]
public uint Ussd_Op_Type;

对于成员的大小有歧义。如果互操作封送使用成员的大小,它将计算4字节,而如果它使用MarshalAs属性,它将计算1字节。修改成员以使用正确的大小类型

[MarshalAs(UnmanagedType.U1)]
public byte Ussd_Op_Type;

应该可以解决这个问题。

因此,在接受@theB的建议后,将U1数据类型声明为字节。问题解决了。更新后的结构定义如下:

[Serializable]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
public struct USSDContinueModel
{
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Length;
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_ID;
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Status;
    [MarshalAs(UnmanagedType.U4)]
    public uint Sender_ID;
    [MarshalAs(UnmanagedType.U4)]
    public uint Receiver_ID;
    [MarshalAs(UnmanagedType.U1)]
    public byte Ussd_Version;
    [MarshalAs(UnmanagedType.U1)]
    public byte Ussd_Op_Type;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string MsIsdn;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string Service_Code;
    [MarshalAs(UnmanagedType.U1)]
    public byte Code_Scheme;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 182)]
    public string Ussd_Content;
    // Calling this method will return a byte array with the contents
    // of the struct ready to be sent via the tcp socket.
    public byte[] Serialize()
    {
        // allocate a byte array for the struct data
        var buffer = new byte[Marshal.SizeOf(typeof(USSDContinueModel))];
        // Allocate a GCHandle and get the array pointer
        var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        var pBuffer = gch.AddrOfPinnedObject();
        // copy data from struct to array and unpin the gc pointer
        Marshal.StructureToPtr(this, pBuffer, false);
        gch.Free();
        return buffer;
    }
    // this method will deserialize a byte array into the struct.
    public void Deserialize(ref byte[] data)
    {
        var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
        this = (USSDContinueModel)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(USSDContinueModel));
        gch.Free();
    }
}