C#之GCHandle


轉載 略談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;
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM