C#非托管内存的应用(二)——结构体拷贝
结构体的转换其实和基础类型数组转换差不多,只是结构体不能通过Marshal.Copy的方式直接转换到内存。 结构体痛byte数组的互转直接用于网络通信中还是非常方便的。
1、定义结构体
/// <summary> /// 测试结构体的Copy /// </summary> public struct TestStruct { public string Number; public int[] IntMember; public byte ByteMember; public short ShortMember; public override string ToString() { return string.Format("Number:" + Number + " ByteMember:" + ByteMember + " ShortMember:" + ShortMember + " IntMemberCount:" + IntMember.Length); } }
2、Copy结构体成byte数组的方法
/// <summary> /// 将结构体直接Copy成byte数组 /// </summary> /// <param name="structObj">必须是结构体</param> /// <param name="targetData">返回的byte数组填充,长度必须大于Marshal.SizeOf(structObj)</param> public static void CopyMemFromStruct(object structObj, byte[] targetData) { IntPtr tmptr = IntPtr.Zero; try { int size = Marshal.SizeOf(structObj); // 获取结构体在内存中的大小 tmptr = Marshal.AllocHGlobal(size); // 为缓冲区分配内存空间 Marshal.StructureToPtr(structObj, tmptr, false); //Copy到分配的非托管内存中 Marshal.Copy(tmptr, targetData, 0, size); Marshal.FreeHGlobal(tmptr); } catch(Exception ex) { if (tmptr != IntPtr.Zero) Marshal.FreeHGlobal(tmptr); throw new Exception("内存操作失败:" + ex.ToString()); } }
3、byte数组Copy成结构体的方法
/// <summary> /// 从byte数组转换成指定的结构体 /// </summary> /// <param name="sourceData"></param> /// <param name="startIndex"></param> /// <param name="length"></param> /// <param name="objectRef"></param> /// <param name="type"></param> public static void CopyMemFromBytes(byte [] sourceData, int startIndex, int length, ref object objectRef, Type type) { IntPtr tmptr = IntPtr.Zero; try { tmptr = Marshal.AllocHGlobal(length); Marshal.Copy(sourceData, startIndex, tmptr, length); objectRef = Marshal.PtrToStructure(tmptr, type); Marshal.FreeHGlobal(tmptr); } catch (Exception ex) { if (tmptr != IntPtr.Zero) Marshal.FreeHGlobal(tmptr); throw new Exception("内存操作失败:" + ex.ToString()); } }
4、测试程序
TestStruct struct1 = new TestStruct(); struct1.ByteMember = 123; struct1.IntMember = new int[] { 1, 3, 45, 4 }; struct1.Number = "test"; struct1.ShortMember = 23241; Console.WriteLine(struct1.ToString()); int size = Marshal.SizeOf(struct1); byte[] testDest = new byte[size]; MemoryCopy.CopyMemFromStruct(struct1, testDest); object struct2 = new TestStruct(); MemoryCopy.CopyMemFromBytes(testDest, 0, size,ref struct2, typeof(TestStruct)); Console.WriteLine(struct2.ToString());