//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();
}
}