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;  
    }  


托管代码 (managed code) :由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。 Unmanaged Code - 非托管代码 :在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。非托管代码的英文名是Unmanaged Code ,它是在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值