You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.2 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Text;
namespace GeoSigmaDrawLib
{
/// <summary>
/// 内存管理辅助类
/// </summary>
public static class MarshalHelper
{
/// <summary>
/// 将 string 转成 C++ 内存数据后调用 func
/// </summary>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="data">要数据的字符串</param>
/// <param name="func">被调用的业务函数</param>
/// <returns>返回 func 的返回值</returns>
public static T Call<T>(string data, Func<IntPtr, int, T> 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);
}
}
}
/// <summary>
/// 将 string 转成 C++ 内存数据后调用 action
/// </summary>
/// <param name="data">要数据的字符串</param>
/// <param name="action">被调用的业务函数</param>
public static void Execute(string data, Action<IntPtr, int> 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);
}
}
}
/// <summary>
/// 将 C++ 内存转换为 string
/// </summary>
/// <param name="pBuff">C++ 内存对应的 IntPtr</param>
/// <returns>当前 pBuff 为 IntPtr.Zero 时,返回空字符串,否则返回对应的字符串</returns>
public static string ToString(IntPtr pBuff)
{
if (pBuff == IntPtr.Zero)
{
return string.Empty;
}
string strData = Marshal.PtrToStringBSTR(pBuff);
Marshal.FreeBSTR(pBuff);
return strData;
}
/// <summary>
/// 将 C++ 的 double 数组(double *,并且必须是 new[]) 转换为 C# 的 double 数组
/// </summary>
/// <param name="pData">double *</param>
/// <param name="length">元素个数</param>
/// <returns>double[]</returns>
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;
}
}
}