我是C#中的菜鸟一个,今天刚刚了解了些C#中的数据类型以及托管,主要是用到了与C 的网络通信,现说下个人的理解吧。
总的来说数据类型分为了值类型和引用类型,再加上存储时的托管与非托管这个.NET新引入的概念,需要保证通信时数据传输的正确性,需要了解下C#与C 两种语言的通信逻辑。
一般来说通信时需要传递的数据主要是以消息头与消息体的两段的形式,而消息头在大多数情况下需要我们自己设计结构体,本来结构体在C#下是值类型,但是当结构体中存在了引用类型的数据时结构体会成为托管类型,但是C 的数据是非托管的,我们需要使用到System.Runtime.interopService命令空间。
先说一下非托管下c#与C 的结构体coding:
C :
- struct head
- {
- char ID[12];
- char NAME[12];
- }
C#:
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- struct UsrDBInfo
- {
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
- public char[] ID;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
- public char[] name;
- }
至于各个关键字的意思含义需要我们使用ctrl k,l以及ctrl k,p去查看
再就是结构体与byte[]之间的转换(借助于非托管内存块IntPtr):
- /*结构与字节数组的转换*/
- //数组类型byte[]是托管的,structObj是托管的,structPtr是非托管的
- //从struct转换到byte[]
- public static byte[] StructToBytes(object structObj)
- {
- //返回结构体的大小(以字节为单位)
- int size = Marshal.SizeOf(structObj);
- //分配大小
- byte[] bytes = new byte[size];
- //分配结构体大小的内存空间
- IntPtr structPtr = Marshal.AllocHGlobal(size);
- try
- {
- //将结构体拷到分配好的内存空间
- //将数据从托管对象structObj封送到非托管内存块structPtr
- Marshal.StructureToPtr(structObj, structPtr, false);
- //Marshal.StructureToPtr(structObj, structPtr, true);
- //将数据从非托管内存指针复制到托管 8 位无符号整数数组
- Marshal.Copy(structPtr, bytes, 0, size);
- return bytes;
- }
- finally
- {
- //释放以前使用 AllocHGlobal 从进程的非托管内存中分配的内存
- Marshal.FreeHGlobal(structPtr);
- }
- }
- //返回类型其实没什么用,从bytes转为strType类型的结构体
- //从byte[]转换为struct
- //使用Info myInfo=(Info)ByteToStruct(bytes, typeof(Info));
- 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);
- try
- {
- //将数据从一维托管数组bytes复制到非托管内存指针strPtr
- Marshal.Copy(bytes, 0, strPtr, size);
- //将数据从非托管内存块封送到新分配的指定类型的托管对象
- //将内存空间转换为目标结构体
- object obj = Marshal.PtrToStructure(strPtr, strType);
- return obj;
- }
- finally
- {
- //释放以前使用 AllocHGlobal 从进程的非托管内存中分配的内存
- Marshal.FreeHGlobal(strPtr);
- }
- }
- //带模板,从字节数组转化为结构体 public static StructType ConverBytesToStructure(byte[] bytesBuffer)
- {
- // 检查长度
- if (bytesBuffer.Length != Marshal.SizeOf(typeof(StructType)))
- {
- throw new ArgumentException("bytesBuffer参数和structObject参数字节长度不一致。");
- }
- //分配一个未托管类型变量
- IntPtr bufferHandler = Marshal.AllocHGlobal(bytesBuffer.Length);
- try
- {
- //可以直接用copy()方法
- for (int index = 0; index < bytesBuffer.Length; index )
- {
- Marshal.WriteByte(bufferHandler, index, bytesBuffer[index]);
- }
- //从非托管类型转化为托管类型变量
- StructType structObject = (StructType)Marshal.PtrToStructure(bufferHandler, typeof(StructType));
- return structObject;
- }
- finally
- {
- //释放非托管类型变量
- Marshal.FreeHGlobal(bufferHandler);
- }
- }
阅读(2827) | 评论(0) | 转发(0) |