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.

173 lines
5.5 KiB
C#

1 month ago
//using CoreWCF.Channels;
using System;
1 month ago
using System.Runtime.InteropServices;
using System.Text;
1 month ago
using System.Xml.Linq;
using UtfUnknown;
1 month ago
namespace GeoSigmaDrawLib
{
/// <summary>
/// 内存管理辅助类
/// </summary>
public static class MarshalHelper
{
1 month ago
private const string GB2312 = "GBK"; // gb18030
static MarshalHelper()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
1 month ago
/// <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>
1 month ago
public static string GetString(IntPtr pBuff)
1 month ago
{
if (pBuff == IntPtr.Zero)
{
return string.Empty;
}
string strData = Marshal.PtrToStringBSTR(pBuff);
Marshal.FreeBSTR(pBuff);
return strData;
}
1 month ago
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);
}
/// <summary>
/// 将指针指向的内存数据转换为字符串
/// </summary>
/// <param name="pBuf">指向数据缓冲区的指针</param>
/// <param name="length">数据的长度(字节数)</param>
/// <returns>转换后的字符串</returns>
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);
}
1 month ago
/// <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;
}
1 month ago
#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();
1 month ago
}
}