Skip to content

Instantly share code, notes, and snippets.

@otuncelli
Created September 7, 2023 04:33
Show Gist options
  • Save otuncelli/686c0ee34e1a0af328583f7af62e9716 to your computer and use it in GitHub Desktop.
Save otuncelli/686c0ee34e1a0af328583f7af62e9716 to your computer and use it in GitHub Desktop.
UTF8 string marshaler
#if !NETSTANDARD2_1_OR_GREATER
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace resvg.net
{
public sealed class UTF8Marshaler : ICustomMarshaler
{
public static readonly UTF8Marshaler Instance = new UTF8Marshaler();
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero)
{
return null;
}
int length = 0;
while (Marshal.ReadByte(pNativeData, length) != 0)
{
length++;
}
byte[] buffer = new byte[length];
Marshal.Copy(pNativeData, buffer, 0, length);
return Encoding.UTF8.GetString(buffer);
}
public 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.");
}
int len = Encoding.UTF8.GetByteCount(str);
len++; // null terminator
byte[] buffer = new byte[len];
Encoding.UTF8.GetBytes(str, 0, str.Length, buffer, 0);
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(buffer, 0, ptr, len);
return ptr;
}
public void CleanUpNativeData(IntPtr pNativeData)
{
if (pNativeData != IntPtr.Zero)
{
Marshal.FreeHGlobal(pNativeData);
}
}
public void CleanUpManagedData(object managedObj)
{
}
public int GetNativeDataSize() => -1;
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment