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