using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace GUI { public class UTF8Marshaler : ICustomMarshaler { static UTF8Marshaler _instance; public IntPtr MarshalManagedToNative(object managedObj) { if(managedObj == null) { return IntPtr.Zero; } if(!(managedObj is string)) { throw new MarshalDirectiveException("UTF8Marshaler must be used on a string."); } // not null terminated byte[] strbuf = Encoding.UTF8.GetBytes((string)managedObj); IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1); Marshal.Copy(strbuf, 0, buffer, strbuf.Length); // write the terminating null Marshal.WriteByte(buffer + strbuf.Length, 0); return buffer; } public object MarshalNativeToManaged(IntPtr pNativeData) { return GetStringFromIntPtr(pNativeData); } public void CleanUpNativeData(IntPtr pNativeData) { //Marshal.FreeHGlobal(pNativeData); } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } public static ICustomMarshaler GetInstance(string cookie) { if(_instance == null) { return _instance = new UTF8Marshaler(); } return _instance; } public static string GetStringFromIntPtr(IntPtr pNativeData) { int offset = 0; byte b = 0; do { b = Marshal.ReadByte(pNativeData, offset); offset++; } while(b != 0); int length = offset - 1; // should not be null terminated byte[] strbuf = new byte[length]; // skip the trailing null Marshal.Copy((IntPtr)pNativeData, strbuf, 0, length); string data = Encoding.UTF8.GetString(strbuf); return data; } } }