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;
        }
    }
}

 

posted @ 2021-02-19 10:10  WellMandala  阅读(1955)  评论(0编辑  收藏  举报