结构数组的通用字节数组转换(C#,hack)

时间:2019-06-17 16:40:13

标签: c# arrays structlayout

有人可以帮助我以这种方式将结构数组转换为字节数组吗?

我从这里开始的代码是:https://stackoverflow.com/a/3577227

这是关于将浮点值的数组强制转换为字节数组,然后使用一些肮脏的肮脏代码将其重新返回,而不进行任何复制。它在数组中包含大量项目的大型项目中具有巨大的使用价值,因此您可以通过写出原始字节直接将它们“解序列化”到文件中。对于基于Plain Old Data结构的类型,此方法之所以有效,是因为除了数据之外,别无他用。

去年,我成功地修改了此代码以使其可与任何struct类型一起使用,但我不幸地丢失了代码。有谁想弄清楚吗?我对此真的很感兴趣。

目标很简单:仅通过更改内部C#数组标头诱使它转换为其他数据类型,即可将结构数组转换为字节数组并再次返回。有可能。

问题在于弄清楚代码中的所有细节。瞥见它的全部功能并将其完美连接。联合可以帮助在任何一个指针上的相同存储器地址上进行写入。这里的所有内容都具有重要的功能,主要是通过反复试验和思考来掌握。

我正在获取的数组头数据可能是主要问题。如果我没记错的话,我会另辟way径。

此代码可以编译,但不能正确更改数组头:

public static unsafe class FastArraySerializer
{
    [StructLayout(LayoutKind.Explicit)]
    private struct Union
    {
        [FieldOffset(0)] public byte[] bytes;
        [FieldOffset(0)] public dynamic data;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct ArrayHeader
    {
        public UIntPtr type;
        public UIntPtr length;
    }

    private static UIntPtr arrayHeaderInfo<T>(T[] data)
    {
        var union = new Union {data = data};
        fixed (void* pBytes = union.bytes)
        {
            return getHeader(pBytes)->type;
        }
    }
    private static UIntPtr arrayHeaderInfo_byteArray()
    {
        fixed (void* pBytes = new byte[1])
        {
            return getHeader(pBytes)->type;
        }
    }



    public static T[] toTypeArray<T>(this byte[] bytes) where T:struct
    {
        var byteArrayLength = bytes.Length;
        var union = new Union {bytes = bytes};
        fixed (void* pArray = union.bytes)
        {
            var pHeader = getHeader(pArray);

            pHeader->type = arrayHeaderInfo(new T[0]);
            var sizeOf = Marshal.SizeOf(new T());
            pHeader->length = (UIntPtr)(byteArrayLength / sizeOf);
        }

        return (T[])union.data;
    }

    public static byte[] toByteArray<T>(this T[] data) where T:struct
    {
        var typeArrayLength = data.Length;
        var union = new Union {data = data};
        fixed(void* pArray = union.bytes)
        {
            var pHeader = getHeader(pArray);

            pHeader->type = arrayHeaderInfo_byteArray();
            var sizeOf = Marshal.SizeOf(new T());
            pHeader->length = (UIntPtr)(typeArrayLength * sizeOf);
        }

        return union.bytes;
    }


    private static ArrayHeader* getHeader(void* pBytes)
    {
        return (ArrayHeader*)pBytes - 1;
    }



}

0 个答案:

没有答案