C# 结构体和字节数组的转换

转自百度文库里的文章,本想下载下来的,但是分值实在太高,所以直接把代码抄了一遍,顺便当做练习。另外,还有一些东西不是很明白。

本文主要起源于项目从C++转到C#时碰到的问题,即套接字发送信息时的类型转换。

在C++中,套接字发送和接收的类型为字符数组char[],而char[]与结构体struct可以直接进行显式转换就可以;

在C#中,Sockets类和NetworkStream类发送和接收的类型为字节数组byte[],而它与结构体的转换并不是非常方便,因此也就有了下文

知识储备:

(1) 需要用到Marshal类,该类提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。

(2) 代码的输入和输出都是托管类型(疑问:结构是值类型,也是托管类型??)

(3) 中间需要用非托管类型作为内容的中转;

下面是代码:

从结构体转到字节数组:

        //byte[]是托管的,structObj是托管的,structPtr是非托管的
        //从struct转换到byte[]
        public static byte[] StructToBytes(object structObj)
        {
            //返回类的非托管大小(以字节为单位)
            int size = Marshal.SizeOf(structObj);

            //分配大小
            byte[] bytes = new byte[size];

            //从进程的非托管堆中分配内存给structPtr
            IntPtr structPtr = Marshal.AllocHGlobal(size);

            //将数据从托管对象structObj封送到非托管内存块structPtr
            Marshal.StructureToPtr(structObj, structPtr, false);

            //Marshal.StructureToPtr(structObj, structPtr, true);
            //将数据从非托管内存指针复制到托管 8 位无符号整数数组
            Marshal.Copy(structPtr, bytes, 0, size);

            //释放以前使用 AllocHGlobal 从进程的非托管内存中分配的内存
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }

从字节数组转到结构体(strType指明了所要转换的结构体类型):

        //返回类型其实没什么用,从bytes转为strType类型的结构体
        //从byte[]转换为struct
        public static object BytesToStruct(byte[] bytes, Type strType)
        {
            //获取结构体的大小(以字节为单位)
            int size = Marshal.SizeOf(strType);
            //简单的判断(可以去掉)
            if (size > bytes.Length)
            {
                return null;
            }

            //从进程的非托管堆中分配内存给structPtr
            IntPtr strPtr = Marshal.AllocHGlobal(size);

            //将数据从一维托管数组bytes复制到非托管内存指针strPtr
            Marshal.Copy(bytes, 0, strPtr, size);

            //将数据从非托管内存块封送到新分配的指定类型的托管对象
            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(strPtr, strType);

            //释放以前使用 AllocHGlobal 从进程的非托管内存中分配的内存
            Marshal.FreeHGlobal(strPtr);
            return obj;
        }

从字节数组类型转为结构体类型(返回值从object直接转为了structType类型的对象)

        //从字节数组转化为结构体
        public StructType ConverBytesToStructure<StructType>(byte[] bytesBuffer)
        {
            // 检查长度
            if (bytesBuffer.Length != Marshal.SizeOf(typeof(StructType)))
            {
                throw new ArgumentException("bytesBuffer参数和structObject参数字节长度不一致。");
            }

            //分配一个未托管类型变量
            IntPtr bufferHandler = Marshal.AllocHGlobal(bytesBuffer.Length);

            //逐个复制,也可以直接用copy()方法
            for (int index = 0; index < bytesBuffer.Length; index++)
            {
                Marshal.WriteByte(bufferHandler, index, bytesBuffer[index]);
            }

            //从非托管类型转化为托管类型变量
            StructType structObject = (StructType)Marshal.PtrToStructure(bufferHandler, typeof(StructType));
            
            //释放非托管类型变量
            Marshal.FreeHGlobal(bufferHandler);

            return structObject;
        }



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值