编组C#结构

我试图序列化以下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"; 

我一直收到错误“类型:USSDcontinueModel不能作为非托管结构编组;不能计算有意义的大小或偏移量”。

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

[MarshalAs(UnmanagedType.U1)]是否是无编组的? 我该怎么办?

问题是定义:

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

关于成员的规模是多么模糊。 如果interop marshal使用成员的大小,它将计算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(); } }