Files
tysdk-intergration/sdk-intergration/LocalPackages/LeviathanVideo/Plugins/Core/UTF8Marshaler.cs
2026-03-24 11:43:22 +08:00

91 lines
2.8 KiB
C#

/*----------------------------------------------------------------
// Copyright (C) 2025 Beijing All rights reserved.
//
// Author: huachangmiao
// Create Date: 2025/04/11
// Module Describe:
//----------------------------------------------------------------*/
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace LeviathanVideo.Abstractions
{
public class UTF8Marshaler : ICustomMarshaler
{
private static readonly UTF8Marshaler Instance = new UTF8Marshaler();
public virtual object MarshalNativeToManaged(IntPtr pNativeData) => FromNative(Encoding.UTF8, pNativeData);
public virtual IntPtr MarshalManagedToNative(object managedObj)
{
if (managedObj == null)
return IntPtr.Zero;
if (!(managedObj is string str))
throw new MarshalDirectiveException($"{GetType().Name} must be used on a string.");
return FromManaged(Encoding.UTF8, str);
}
public virtual void CleanUpNativeData(IntPtr pNativeData)
{
//Free anything allocated by MarshalManagedToNative
//This is called after the native function call completes
if (pNativeData != IntPtr.Zero)
Marshal.FreeHGlobal(pNativeData);
}
public void CleanUpManagedData(object managedObj)
{
//Free anything allocated by MarshalNativeToManaged
//This is called after the native function call completes
}
public int GetNativeDataSize() => -1; // Not a value type
public static ICustomMarshaler GetInstance(string cookie) => Instance;
public static unsafe string FromNative(Encoding encoding, IntPtr pNativeData) => FromNative(encoding, (byte*)pNativeData);
public static unsafe string FromNative(Encoding encoding, byte* pNativeData)
{
if (pNativeData == null)
return null;
var start = pNativeData;
var walk = start;
// Find the end of the string
while (*walk != 0) walk++;
if (walk == start)
return string.Empty;
return new string((sbyte*)pNativeData, 0, (int)(walk - start), encoding);
}
public static unsafe IntPtr FromManaged(Encoding encoding, string value)
{
if (encoding == null || value == null)
return IntPtr.Zero;
var length = encoding.GetByteCount(value);
var buffer = (byte*)Marshal.AllocHGlobal(length + 1).ToPointer();
if (length > 0)
{
fixed (char* pValue = value)
{
encoding.GetBytes(pValue, value.Length, buffer, length);
}
}
buffer[length] = 0;
return new IntPtr(buffer);
}
}
}