轉載 略談GCHandle
C# - Marshal.StructureToPtr方法簡介
Marshal類 兩個方法StructureToPtr和PtrToStructure實現序列化 字節 數組 轉換
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace GCHandleExcerse { class Program { static void Main(string[] args) { People p1 = new People(10,180,"李白"); byte[]buff=Struct2Bytes(p1); foreach (var i in buff) { Console.Write(i+"\t"); } People p2= ByteToStruct<People>(buff); Console.WriteLine(); Console.WriteLine(p2.Age+"\t"+p2.Name+"\t"+p2.Height);//輸出10 李白 180 Console.ReadKey(); } //結構體轉換為byte數組 private static byte[] Struct2Bytes(object o) { // create a new byte buffer the size of your struct byte[] buffer = new byte[Marshal.SizeOf(o)]; // pin the buffer so we can copy data into it w/o GC collecting it GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);//為指定的對象分配句柄,不通過GC回收,而是通過手動釋放 // copy the struct data into the buffer //StructureToPtr參數1:托管對象,包含要封送的數據。該對象必須是格式化類的實例。 //StructureToPtr參數2:指向非托管內存塊的指針,必須在調用此方法之前分配該指針。 //StructureToPtr參數3:設置為 true 可在執行Marshal.DestroyStructure方法前對 ptr 參數調用此方法。請注意,傳遞 false 可導致內存泄漏。 // bufferHandle.AddrOfPinnedObject():檢索對象的地址並返回 Marshal.StructureToPtr(o, bufferHandle.AddrOfPinnedObject(), false);//將數據從托管對象封送到非托管內存塊。 // free the GC handle bufferHandle.Free(); return buffer; } //將byte數組轉換為結構體 public static T ByteToStruct<T>(byte[] by) where T : struct { int objectSize = Marshal.SizeOf(typeof(T)); if (objectSize > by.Length) return default(T); // 分配內存 IntPtr buffer = Marshal.AllocHGlobal(objectSize); // 將數據復制到內存中 Marshal.Copy(by, 0, buffer, objectSize); // Push the memory into a new struct of type (T).將數據封送到結構體T中 T returnStruct = (T)Marshal.PtrToStructure(buffer, typeof(T)); // Free the unmanaged memory block.釋放內存 Marshal.FreeHGlobal(buffer); return returnStruct; } } struct People { public uint Age; public ushort Height; public string Name; public People(uint age, ushort height, string name) { this.Age = age; this.Height = height; this.Name = name; } } }