C#非托管内存的应用(二)——结构体拷贝

2023-05-19,,

  结构体的转换其实和基础类型数组转换差不多,只是结构体不能通过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());

《C#非托管内存的应用(二)——结构体拷贝.doc》

下载本文的Word格式文档,以方便收藏与打印。