C# 结构体和字节数组的转换
2017-07-07 09:57
721 查看
转自百度文库里的文章,本想下载下来的,但是分值实在太高,所以直接把代码抄了一遍,顺便当做练习。另外,还有一些东西不是很明白。
本文主要起源于项目从C++转到C#时碰到的问题,即套接字发送信息时的类型转换。
在C++中,套接字发送和接收的类型为字符数组char[],而char[]与结构体struct可以直接进行显式转换就可以;
在C#中,Sockets类和NetworkStream类发送和接收的类型为字节数组byte[],而它与结构体的转换并不是非常方便,因此也就有了下文
知识储备:
(1) 需要用到Marshal类,该类提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。
(2) 代码的输入和输出都是托管类型(疑问:结构是值类型,也是托管类型??)
(3) 中间需要用非托管类型作为内容的中转;
下面是代码:
从结构体转到字节数组:
从字节数组转到结构体(strType指明了所要转换的结构体类型):
从字节数组类型转为结构体类型(返回值从object直接转为了structType类型的对象)
托管代码 (managed code) :由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。
Unmanaged Code -
非托管代码 :在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。非托管代码的英文名是Unmanaged
Code ,它是在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。
本文主要起源于项目从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, bc94 index, bytesBuffer[index]); } //从非托管类型转化为托管类型变量 StructType structObject = (StructType)Marshal.PtrToStructure(bufferHandler, typeof(StructType)); //释放非托管类型变量 Marshal.FreeHGlobal(bufferHandler); return structObject; }
托管代码 (managed code) :由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。
Unmanaged Code -
非托管代码 :在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。非托管代码的英文名是Unmanaged
Code ,它是在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中获得这些服务。
相关文章推荐
- C#结构体和字节数组的转换
- C#结构体和字节数组的转换
- C#结构体和字节数组的转换
- C#中结构体和字节数组转换实现
- C#结构体和字节数组的转换
- C# 结构体定义 转换字节数组 z
- C# 转换uint,byte[],char[],string, short[]<->byte[] 结构体和字节数组转化
- C#结构体和字节数组的转换
- [C#]结构体间实现用户定义的转换
- C#与C++数据类型比较及结构体转换(搜集整理二)
- C#调用C++DLL数据封送结构体转换工具
- 结构体和二进制数据相互转换c#(good)
- c#中关于结构体和字节数组转化
- C# 结构体和指针转换
- c#中关于结构体和字节数组转化
- (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换
- C# 结构体转换byte
- C# 中将数值型数据转换为字节数组的方法
- C# 结构体和指针转换
- C# 数值型数据转换为字节数组