编组Struct的一部分

时间:2014-04-28 05:14:15

标签: c# marshalling

我一直试图弄清楚是否有可能将结构的一部分编组为一个字节数组而没有任何错误。原因是因为不打算编组的部分具有可变大小的数组。这是我正在使用的代码。

    public struct Random
    {
        [MarshalAs(UnmanagedType.I4)]
        public int a;
        [MarshalAs(UnmanagedType.I4)]
        public int b;
        [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_RECORD)]
        public Random1[] r;
    }

    public struct Random1
    {
        [MarshalAs(UnmanagedType.I4)]
        public int c;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        int size = Marshal.SizeOf(typeof(Random));
        int s = 4;
        Random r = new Random();
        Random r1 = new Random();

        r.a = 1;
        r.b = 5;
        r.r = new Random1[2];
        r.r[0].c = 10;
        r.r[1].c = 12;

        IntPtr p = Marshal.AllocHGlobal(size);
        try
        {
            byte[] arr = new byte[size];
            Marshal.StructureToPtr(r, p, false);
            Marshal.Copy(p, arr, 0, 8);
            Marshal.FreeHGlobal(p);
            p = Marshal.AllocHGlobal(size);
            Marshal.Copy(arr,0,p,8);
            r1 = (Random)Marshal.PtrToStructure(p, typeof(Random));
            Marshal.FreeHGlobal(p);
            p = IntPtr.Zero;
            Debug.WriteLine(r1.a);
            Debug.WriteLine(r1.b);
            Debug.WriteLine(r1.r[0].c);
            Debug.WriteLine(r1.r[1].c);
        }
        finally
        {
            if (p != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(p);
            }
        }
    }

当我尝试这个代码时,它在StructureToPtr中给了我一个ArgumentException。我做错了什么或者能做到这一点?如果不是我读过有关使用IntPtr的内容,有人可以告诉我该怎么做吗?

1 个答案:

答案 0 :(得分:0)

我一直在思考这个问题,在尝试了几个(非常 hackish)选项后,我得出的结论是,你所做的事情是不可能的。< / p>

首先,不可能直接编组一个可变长度的数组,因为Marshal不能计算出有意义的大小偏移量,因此无法确定内存布局。

如果结构不包含任何非blittable,非原始类型,理论上你可以这样做:

byte[] buffer = new byte[8];
Marshal.Copy(new IntPtr(&r), buffer, 0, 8);

IntegersOnlyStruct partialStruct;
fixed (byte* b = buffer)
    partialStruct = *(IntegersOnlyStruct*) b;

并获取结构中包含的两个整数。但是,由于你的Random1是一种非原始的,非盲目的类型,这种方法也不会让你走得很远。

保持指向内存位置的IntPtr方法,将Random1结构保存在内存中是另一种可能有效的方法,但我还没有深入研究那,但是。

我认为你可能想重新思考一下这种方式,因为它目前的形式是不可能的。如果有人能证明不是这样,我很高兴看到它是如何完成的。