using System; using System.Runtime.InteropServices; using System.Text; namespace GeoSigmaDrawLib { /// /// 内存管理辅助类 /// public static class MarshalHelper { /// /// 将 string 转成 C++ 内存数据后调用 func /// /// 返回值类型 /// 要数据的字符串 /// 被调用的业务函数 /// 返回 func 的返回值 public static T Call(string data, Func func) { IntPtr pBuff = IntPtr.Zero; try { pBuff = Marshal.StringToHGlobalAnsi(data); int nLen = Encoding.Default.GetByteCount(data); return func(pBuff, nLen); } finally { if (pBuff != IntPtr.Zero) { Marshal.FreeHGlobal(pBuff); } } } /// /// 将 string 转成 C++ 内存数据后调用 action /// /// 要数据的字符串 /// 被调用的业务函数 public static void Execute(string data, Action action) { IntPtr pBuff = IntPtr.Zero; try { pBuff = Marshal.StringToHGlobalAnsi(data); int nLen = Encoding.Default.GetByteCount(data); action(pBuff, nLen); } finally { if (pBuff != IntPtr.Zero) { Marshal.FreeHGlobal(pBuff); } } } /// /// 将 C++ 内存转换为 string /// /// C++ 内存对应的 IntPtr /// 当前 pBuff 为 IntPtr.Zero 时,返回空字符串,否则返回对应的字符串 public static string ToString(IntPtr pBuff) { if (pBuff == IntPtr.Zero) { return string.Empty; } string strData = Marshal.PtrToStringBSTR(pBuff); Marshal.FreeBSTR(pBuff); return strData; } /// /// 将 C++ 的 double 数组(double *,并且必须是 new[]) 转换为 C# 的 double 数组 /// /// double * /// 元素个数 /// double[] public static double[] ToDoubleArray(IntPtr pData, int length) { if (pData == IntPtr.Zero) { throw new ArgumentException($"{nameof(pData)} cannot be equal to IntPtr.Zero"); } if (length <= 0) { throw new ArgumentOutOfRangeException(nameof(length), "Length must be greater than zero."); } double[] result = new double[length]; Marshal.Copy(pData, result, 0, length); GeoSigmaLib.PointerArrayDelete(pData); return result; } } }