Marshalling a C# structure

冷暖自知 提交于 2019-12-07 09:18:27

The problem is that the definition:

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

is ambiguous as to what size the members could be. If the interop marshal uses the member's size, it will calculate 4 bytes, whereas if it uses the MarshalAs attribute it will calculate 1 byte. Changing the member to use the correct size type,

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

should fix the issue.

So after taking @theB's recommendation of declaring the U1 data types as bytes. The problem was resolved. The updated structure definition follows:

[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();
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!