//using CoreWCF.Channels; using System; using System.Runtime.InteropServices; using System.Text; using System.Xml.Linq; using UtfUnknown; namespace GeoSigmaDrawLib { /// /// 内存管理辅助类 /// public static class MarshalHelper { private const string GB2312 = "GBK"; // gb18030 static MarshalHelper() { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); } /// /// 将 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 GetString(IntPtr pBuff) { if (pBuff == IntPtr.Zero) { return string.Empty; } string strData = Marshal.PtrToStringBSTR(pBuff); Marshal.FreeBSTR(pBuff); return strData; } public static string GetUtf8String(IntPtr pBuf, int length) { if (pBuf == IntPtr.Zero || length <= 0) { return string.Empty; } byte[] data = new byte[length]; Marshal.Copy(pBuf, data, 0, length); return Encoding.UTF8.GetString(data); } public static string GetGbkString(IntPtr pBuf, int length) { if (pBuf == IntPtr.Zero || length <= 0) { return string.Empty; } byte[] data = new byte[length]; Marshal.Copy(pBuf, data, 0, length); var gb2312 = Encoding.GetEncoding(GB2312); return gb2312.GetString(data); } /// /// 将指针指向的内存数据转换为字符串 /// /// 指向数据缓冲区的指针 /// 数据的长度(字节数) /// 转换后的字符串 public static string PtrToCharsetString(IntPtr pBuf, int length) { if (pBuf == IntPtr.Zero || length <= 0) { return string.Empty; } int nDllCharacterSet = GetDllCharacterSet(); Encoding encoding = Encoding.Unicode; // UTF-16 LE if (nDllCharacterSet == 0) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); encoding = Encoding.GetEncoding(GB2312); } byte[] data = new byte[length]; Marshal.Copy(pBuf, data, 0, length); return encoding.GetString(data); } /// /// 将 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; } #if DEBUG const string SIGMALIB = "GeoSigmaDraw.dll"; #else const string SIGMALIB = "GeoSigmaDraw.dll"; #endif [DllImport(SIGMALIB, EntryPoint = "GetDllCharacterSet", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)] public static extern int GetDllCharacterSet(); } }