//------------------------------------------------------------ // Game Framework // Copyright © 2013-2021 loyalsoft. All rights reserved. // Homepage: http://www.game7000.com/ // Feedback: http://www.game7000.com/ //------------------------------------------------------------ using System; namespace GameFramework { public static partial class Utility { /// /// Marshal 相关的实用函数。 /// public static class Marshal { private const int BlockSize = 1024 * 4; private static IntPtr s_CachedHGlobalPtr = IntPtr.Zero; private static int s_CachedHGlobalSize = 0; /// /// 获取缓存的从进程的非托管内存中分配的内存的大小。 /// public static int CachedHGlobalSize { get { return s_CachedHGlobalSize; } } /// /// 确保从进程的非托管内存中分配足够大小的内存并缓存。 /// /// 要确保从进程的非托管内存中分配内存的大小。 public static void EnsureCachedHGlobalSize(int ensureSize) { if (ensureSize < 0) { throw new GameFrameworkException("Ensure size is invalid."); } if (s_CachedHGlobalPtr == IntPtr.Zero || s_CachedHGlobalSize < ensureSize) { FreeCachedHGlobal(); int size = (ensureSize - 1 + BlockSize) / BlockSize * BlockSize; s_CachedHGlobalPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size); s_CachedHGlobalSize = size; } } /// /// 释放缓存的从进程的非托管内存中分配的内存。 /// public static void FreeCachedHGlobal() { if (s_CachedHGlobalPtr != IntPtr.Zero) { System.Runtime.InteropServices.Marshal.FreeHGlobal(s_CachedHGlobalPtr); s_CachedHGlobalPtr = IntPtr.Zero; s_CachedHGlobalSize = 0; } } /// /// 将数据从对象转换为二进制流。 /// /// 要转换的对象的类型。 /// 要转换的对象。 /// 存储转换结果的二进制流。 public static byte[] StructureToBytes(T structure) { return StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T))); } /// /// 将数据从对象转换为二进制流。 /// /// 要转换的对象的类型。 /// 要转换的对象。 /// 要转换的对象的大小。 /// 存储转换结果的二进制流。 internal static byte[] StructureToBytes(T structure, int structureSize) { if (structureSize < 0) { throw new GameFrameworkException("Structure size is invalid."); } EnsureCachedHGlobalSize(structureSize); System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true); byte[] result = new byte[structureSize]; System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, 0, structureSize); return result; } /// /// 将数据从对象转换为二进制流。 /// /// 要转换的对象的类型。 /// 要转换的对象。 /// 存储转换结果的二进制流。 public static void StructureToBytes(T structure, byte[] result) { StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), result, 0); } /// /// 将数据从对象转换为二进制流。 /// /// 要转换的对象的类型。 /// 要转换的对象。 /// 要转换的对象的大小。 /// 存储转换结果的二进制流。 internal static void StructureToBytes(T structure, int structureSize, byte[] result) { StructureToBytes(structure, structureSize, result, 0); } /// /// 将数据从对象转换为二进制流。 /// /// 要转换的对象的类型。 /// 要转换的对象。 /// 存储转换结果的二进制流。 /// 写入存储转换结果的二进制流的起始位置。 public static void StructureToBytes(T structure, byte[] result, int startIndex) { StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), result, startIndex); } /// /// 将数据从对象转换为二进制流。 /// /// 要转换的对象的类型。 /// 要转换的对象。 /// 要转换的对象的大小。 /// 存储转换结果的二进制流。 /// 写入存储转换结果的二进制流的起始位置。 internal static void StructureToBytes(T structure, int structureSize, byte[] result, int startIndex) { if (structureSize < 0) { throw new GameFrameworkException("Structure size is invalid."); } if (result == null) { throw new GameFrameworkException("Result is invalid."); } if (startIndex < 0) { throw new GameFrameworkException("Start index is invalid."); } if (startIndex + structureSize > result.Length) { throw new GameFrameworkException("Result length is not enough."); } EnsureCachedHGlobalSize(structureSize); System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true); System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, startIndex, structureSize); } /// /// 将数据从二进制流转换为对象。 /// /// 要转换的对象的类型。 /// 要转换的二进制流。 /// 存储转换结果的对象。 public static T BytesToStructure(byte[] buffer) { return BytesToStructure(System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), buffer, 0); } /// /// 将数据从二进制流转换为对象。 /// /// 要转换的对象的类型。 /// 要转换的二进制流。 /// 读取要转换的二进制流的起始位置。 /// 存储转换结果的对象。 public static T BytesToStructure(byte[] buffer, int startIndex) { return BytesToStructure(System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), buffer, startIndex); } /// /// 将数据从二进制流转换为对象。 /// /// 要转换的对象的类型。 /// 要转换的对象的大小。 /// 要转换的二进制流。 /// 存储转换结果的对象。 internal static T BytesToStructure(int structureSize, byte[] buffer) { return BytesToStructure(structureSize, buffer, 0); } /// /// 将数据从二进制流转换为对象。 /// /// 要转换的对象的类型。 /// 要转换的对象的大小。 /// 要转换的二进制流。 /// 读取要转换的二进制流的起始位置。 /// 存储转换结果的对象。 internal static T BytesToStructure(int structureSize, byte[] buffer, int startIndex) { if (structureSize < 0) { throw new GameFrameworkException("Structure size is invalid."); } if (buffer == null) { throw new GameFrameworkException("Buffer is invalid."); } if (startIndex < 0) { throw new GameFrameworkException("Start index is invalid."); } if (startIndex + structureSize > buffer.Length) { throw new GameFrameworkException("Buffer length is not enough."); } EnsureCachedHGlobalSize(structureSize); System.Runtime.InteropServices.Marshal.Copy(buffer, startIndex, s_CachedHGlobalPtr, structureSize); return (T)System.Runtime.InteropServices.Marshal.PtrToStructure(s_CachedHGlobalPtr, typeof(T)); } } } }