错误:指定的结构必须是blittable或具有布局信息

时间:2014-08-22 05:15:02

标签: c# marshalling

public class TestSerializer
{
    public static byte[] StructureToByteArray(Test[] array)
    {
        int size = Marshal.SizeOf(array.Length);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(array, ptr, true);//error
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);
        return arr;
    }

当我写上面的代码时,我收到了这个错误。但我的结构是这样的:

public struct Test
{
   [FieldOffset(0)]
   //   public string name;

    public Byte  icode;

    [FieldOffset(1)]
    public Byte method;

    [FieldOffset(2)]
    public Byte wav;

    [FieldOffset(3)]
    public Byte wav2;

    [FieldOffset(4)]
    public Byte unit;

    [FieldOffset(5)]
    public Byte temp;
    [fieldOffset(6)]
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public byte[] itemname;

    //public float factor;
}

Test[] array = new Test[200];

我想将这个'数组'转换为字节数组,我也对下一行有疑问

int size = Marshal.SizeOf(array.Length);

是否可能像写这个

阵列[1] .itemname = ASD;

1 个答案:

答案 0 :(得分:2)

尝试将属性[StructLayout(LayoutKind.Explicit)]添加到struct test

Marshal.SizeOf(array.Length)解析为Marshal.SizeOf(200) - 200是int32,其报告大小为4.您需要执行array.Length * Marshal.SizeOf(typeof(Test))

问题是Test类型数组不是blittable according to the documentation(如果你用[StructLayout(LayoutKind.Explicit)]LayoutKind.Sequential标记了结构本身,那么你需要它)在循环中自己做。

public static byte[] StructureToByteArray(Test[] array)
    {
        int structSize = Marshal.SizeOf(typeof(Test));
        int size = array.Length * structSize;
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);
        for (int i = 0; i < array.Length; i++ )
            Marshal.StructureToPtr(array[i], ptr+i*structSize, true);//error
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);
        return arr;
    }

数组必须以4字节边界开始,因此结构应如下所示:

[StructLayout(LayoutKind.Explicit)]
public struct Test
{
    [FieldOffset(0)]
    public byte icode;

    [FieldOffset(1)]
    public byte method;

    [FieldOffset(2)]
    public byte wav;

    [FieldOffset(3)]
    public byte wav2;

    [FieldOffset(4)]
    public byte unit;

    [FieldOffset(5)]
    public byte temp;

    [FieldOffset(8)]
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public byte[] itemname;
}

字符串赋值可以通过将字符串编码到字节数组中并复制到结构中来完成,如下所示:

 Test[] array = new Test[200];
 byte[] temp = Encoding.UTF8.GetBytes("asd");
 array[0].itemname = new byte[20];
 Array.Copy(temp, array[0].itemname, temp.Length);