在C#中将结构体转换为字节数组

3

我有一个类内部的结构体:

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)]
public struct MyStruct
{
    public byte StartOfText;
    public byte DisableChecksum;
    public byte ProtocolVersion;
    public byte Code;
    public Int16 Size;
    public byte[] Data;
    public byte EndOfText;

    public MyStruct(CommandCode commandCode, string commandData)
    {
        this.StartOfText = 0x02;
        this.DisableChecksum = 0x00;
        this.ProtocolVersion = 0x35;
        this.Code = (byte)commandCode;
        this.Size = (Int16)commandData.Length;
        this.Data = new byte[commandData.Length];
        this.Data = Encoding.ASCII.GetBytes(commandData);
        this.EndOfText = 0x03;
    }

    public byte[] ToByteArray()
    {
        byte[] arr = null;
        IntPtr ptr = IntPtr.Zero;
        try
        {
            Int16 size = (Int16)Marshal.SizeOf(this);
            arr = new byte[size];
            ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(this, ptr, true);
            Marshal.Copy(ptr, arr, 0, size);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            Marshal.FreeHGlobal(ptr);
        }

        return arr;
    }
}

现在,假设我在我的程序中通过以下方式初始化一个新的结构体实例:
Protocol.MyStruct Cmd = new Protocol.MyStruct(CommandCode.LOAD_FILE, "TEST");
byte[] StructData = Cmd.ToByteArray();

初始化时,我可以看到MyStruct.Data被正确地初始化为字符串常量的内容(0x54、0x45、0x53、0x54)。每个字符都被正确地复制。
但是,当调用MyStruct.TiByteArray()并跟踪数组中的值时,Data部分现在变成了(0xa0, 0xa6, 0x91和0x03)。
数组的其余部分都没问题,数据被正确地复制了。
我的代码有什么问题?或者说我漏掉了什么?

你的构造函数正在创建两个字节数组并丢弃第一个。 - ChaosPandion
我的猜测是字节数组的引用正在被序列化。 - ChaosPandion
看一下这个: - Oualid KTATA
使用非托管内存(AllocHGlobal)似乎有些过度设计。 - bohdan_trotsenko
1个回答

2

在某些情况下,这可能有效。但是,Data的长度是固定的。如果将Data定义为字符串,则可能更有用。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyStruct
{
    const int ARRAY_SIZE = 100;

    public byte StartOfText;
    public byte DisableChecksum;
    public byte ProtocolVersion;
    public byte Code;
    public Int16 Size;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = ARRAY_SIZE)]
    public byte[] Data;
    public byte EndOfText;

    public MyStruct(CommandCode commandCode, string commandData)
    {
        this.StartOfText = 0x02;
        this.DisableChecksum = 0x00;
        this.ProtocolVersion = 0x35;
        this.Code = (byte)commandCode;
        this.Size = (Int16)commandData.Length;
        this.Data = new byte[ARRAY_SIZE];
        byte[] bytes = Encoding.ASCII.GetBytes(commandData);
        Array.Copy(bytes, Data, bytes.Length);
        //this.Data = Encoding.ASCII.GetBytes(commandData);
        this.EndOfText = 0x03;
    }

    public byte[] ToByteArray()
    {
        byte[] arr = null;
        IntPtr ptr = IntPtr.Zero;
        try
        {
            int size = Marshal.SizeOf(this);
            arr = new byte[size];
            ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(this, ptr, true);
            Marshal.Copy(ptr, arr, 0, size);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            Marshal.FreeHGlobal(ptr);
        }

        return arr;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接