diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllLinuxPInvoker.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllLinuxPInvoker.cs index 2ff5d229..9253691d 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllLinuxPInvoker.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllLinuxPInvoker.cs @@ -32,8 +32,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices public static extern void FreeSlice([In] IntPtr slice); [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))] - public static extern string GetContentFromSlice([In] IntPtr slice); + public static extern IntPtr GetContentFromSlice([In] IntPtr slice); [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern int GetSliceLen([In] IntPtr slice); @@ -45,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices public static extern void FreeMediaData([In] IntPtr mediaData); [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] - public static extern string GetOutIndexBuf([In] IntPtr mediaData); + public static extern IntPtr GetOutIndexBuf([In] IntPtr mediaData); [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr GetData([In] IntPtr mediaData); diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllWindowsPInvoker.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllWindowsPInvoker.cs index 1a4abf1d..1f7a1c38 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllWindowsPInvoker.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/FinanceDllWindowsPInvoker.cs @@ -42,8 +42,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))] - public static extern string GetContentFromSlice([In] IntPtr slice); + public static extern IntPtr GetContentFromSlice([In] IntPtr slice); [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] [SuppressUnmanagedCodeSecurity] @@ -59,7 +58,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] [SuppressUnmanagedCodeSecurity] - public static extern string GetOutIndexBuf([In] IntPtr mediaData); + public static extern IntPtr GetOutIndexBuf([In] IntPtr mediaData); [DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] [SuppressUnmanagedCodeSecurity] diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/MarshalerHelper.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/MarshalerHelper.cs new file mode 100644 index 00000000..8c1bcc47 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/MarshalerHelper.cs @@ -0,0 +1,41 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices +{ + internal static class MarshalerHelper + { + public static string PtrToStringAnsi(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return default!; + + return Marshal.PtrToStringAnsi(ptr)!; + } + + public static string PtrToStringUTF8(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return default!; + +#if NETCOREAPP || NET5_0_OR_GREATER + return Marshal.PtrToStringUTF8(ptr)!; +#else + byte b; + int offset = 0; + + do + { + b = Marshal.ReadByte(ptr, offset); + offset++; + } + while (b != 0); + + byte[] bytes = new byte[offset - 1]; + Marshal.Copy(ptr, bytes, 0, bytes.Length); + return Encoding.UTF8.GetString(bytes); +#endif + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/UTF8Marshaler.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/UTF8Marshaler.cs deleted file mode 100644 index 2651ea41..00000000 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/InteropServices/UTF8Marshaler.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices -{ - internal sealed class UTF8Marshaler : ICustomMarshaler - { - private static readonly Lazy _instance = new Lazy(() => new UTF8Marshaler()); - - public static ICustomMarshaler GetInstance(string pstrCookie) - { - return _instance.Value; - } - - public static string? PtrToStringUTF8(IntPtr pNativeData) - { - return _instance.Value.MarshalNativeToManaged(pNativeData) as string; - } - - public IntPtr MarshalManagedToNative(object managedObj) - { - if (managedObj is null) - return IntPtr.Zero; - if (!(managedObj is string)) - throw new InvalidOperationException(); - - byte[] bytes = Encoding.UTF8.GetBytes((string)managedObj); - IntPtr pNativeData = Marshal.AllocHGlobal(bytes.Length + 1); - Marshal.Copy(bytes, 0, pNativeData, bytes.Length); - Marshal.WriteByte(pNativeData, bytes.Length, 0); - return pNativeData; - } - - public object MarshalNativeToManaged(IntPtr pNativeData) - { - if (pNativeData == IntPtr.Zero) - return default!; - -#if NETCOREAPP || NET5_0_OR_GREATER - return Marshal.PtrToStringUTF8(pNativeData)!; -#else - byte b; - int offset = 0; - - do - { - b = Marshal.ReadByte(pNativeData, offset); - offset++; - } - while (b != 0); - - byte[] bytes = new byte[offset - 1]; - Marshal.Copy(pNativeData, bytes, 0, bytes.Length); - return Encoding.UTF8.GetString(bytes); -#endif - } - - public void CleanUpManagedData(object managedObj) - { - } - - public void CleanUpNativeData(IntPtr pNativeData) - { - if (pNativeData == IntPtr.Zero) - { - return; - } - - /** - * NOTICE: - * 这里释放内存会导致外部 P/Invoke 调用 FreeSlice() 方法时抛出异常 - * 因此请注释下面的代码 - */ - // Marshal.FreeHGlobal(pNativeData); - } - - public int GetNativeDataSize() - { - return -1; - } - } -} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/WechatWorkFinanceClient.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/WechatWorkFinanceClient.cs index 96a05b05..9404e551 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/WechatWorkFinanceClient.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/SDK/Finance/WechatWorkFinanceClient.cs @@ -129,10 +129,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance // IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) : // IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) : // throw new PlatformNotSupportedException(); - string dataContent = /* 获取聊天记录数据内容 */ + IntPtr dataContentPtr = /* 获取聊天记录数据内容 */ IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) : IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) : throw new PlatformNotSupportedException(); + string dataContent = MarshalerHelper.PtrToStringUTF8(dataContentPtr); response = JsonSerializer.Deserialize(dataContent); response.RawBytes = Encoding.UTF8.GetBytes(dataContent); @@ -220,10 +221,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance // IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) : // IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) : // throw new PlatformNotSupportedException(); - string dataContent = /* 获取聊天记录数据内容 */ + IntPtr dataContentPtr = /* 获取聊天记录数据内容 */ IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) : IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) : throw new PlatformNotSupportedException(); + string dataContent = MarshalerHelper.PtrToStringUTF8(dataContentPtr); response = JsonSerializer.Deserialize(dataContent); response.RawBytes = Encoding.UTF8.GetBytes(dataContent); @@ -293,7 +295,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetData(dataPtr) : IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetData(dataPtr) : throw new PlatformNotSupportedException(); - string dataNextBufferIndex = /* 获取媒体文件数据内容缓冲标识 */ + IntPtr dataNextBufferIndex = /* 获取媒体文件数据内容缓冲标识 */ IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetOutIndexBuf(dataPtr) : IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetOutIndexBuf(dataPtr) : throw new PlatformNotSupportedException(); @@ -304,10 +306,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance byte[] bytes = new byte[dataSize]; Marshal.Copy(dataContentPtr, bytes, 0, bytes.Length); - Marshal.FreeHGlobal(dataContentPtr); response.FileBufferBytes = bytes; - response.NextBufferIndex = dataNextBufferIndex; + response.NextBufferIndex = MarshalerHelper.PtrToStringAnsi(dataNextBufferIndex); response.IsFinished = dataIsFinishFlag != 0; }