/* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma warning disable 1591 using System; using System.Linq; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Reflection; using System.ComponentModel; using System.Globalization; using Eina.Callbacks; using static Eina.HashNativeFunctions; using static Eina.InarrayNativeFunctions; using static Eina.InlistNativeFunctions; using static Eina.NativeCustomExportFunctions; namespace Eina { [EditorBrowsable(EditorBrowsableState.Never)] internal enum ElementType { NumericType, StringType, StringshareType, ObjectType }; [EditorBrowsable(EditorBrowsableState.Never)] [StructLayout(LayoutKind.Sequential)] internal struct InlistMem : IEquatable { public IntPtr next {get;set;} public IntPtr prev {get;set;} public IntPtr last {get;set;} /// /// Gets a hash for . /// Since EFL 1.24. /// /// A hash code. public override int GetHashCode() => next.GetHashCode() ^ prev.GetHashCode() ^ last.GetHashCode(); /// Returns whether this /// is equal to the given . /// Since EFL 1.24. /// /// The to be compared to. /// true if is equal to other. public override bool Equals(object other) => (!(other is InlistMem)) ? false : Equals((InlistMem)other); /// Returns whether this is equal /// to the given . /// Since EFL 1.24. /// /// The to be compared to. /// true if is equal to other. public bool Equals(InlistMem other) => (next == other.next) && (prev == other.prev) && (last == other.last); /// Returns whether lhs is equal to rhs. /// Since EFL 1.24. /// /// The left hand side of the operator. /// The right hand side of the operator. /// true if lhs is equal /// to rhs. public static bool operator==(InlistMem lhs, InlistMem rhs) => lhs.Equals(rhs); /// Returns whether lhs is not equal to rhs. /// Since EFL 1.24. /// /// The left hand side of the operator. /// The right hand side of the operator. /// true if lhs is not equal /// to rhs. public static bool operator!=(InlistMem lhs, InlistMem rhs) => !(lhs == rhs); } [EditorBrowsable(EditorBrowsableState.Never)] [StructLayout(LayoutKind.Sequential)] internal struct InlistNode : IEquatable> { public InlistMem __in_list {get;set;} public T Val {get;set;} /// /// Gets a hash for . /// Since EFL 1.24. /// /// A hash code. public override int GetHashCode() => __in_list.GetHashCode() ^ Val.GetHashCode(); /// Returns whether this /// is equal to the given . /// Since EFL 1.24. /// /// The to be compared to. /// true if is equal to other. public override bool Equals(object other) => (!(other is InlistNode)) ? false : Equals((InlistNode)other); /// Returns whether this is equal /// to the given . /// Since EFL 1.24. /// /// The to be compared to. /// true if is equal to other. public bool Equals(InlistNode other) => (__in_list == other.__in_list) && (Val.Equals(other.Val)); /// Returns whether lhs is equal to rhs. /// Since EFL 1.24. /// /// The left hand side of the operator. /// The right hand side of the operator. /// true if lhs is equal /// to rhs. public static bool operator==(InlistNode lhs, InlistNode rhs) => lhs.Equals(rhs); /// Returns whether lhs is not equal to rhs. /// Since EFL 1.24. /// /// The left hand side of the operator. /// The right hand side of the operator. /// true if lhs is not equal /// to rhs. public static bool operator!=(InlistNode lhs, InlistNode rhs) => !(lhs == rhs); } [EditorBrowsable(EditorBrowsableState.Never)] internal interface IBaseElementTraits { IntPtr ManagedToNativeAlloc(T man); IntPtr ManagedToNativeAllocInlistNode(T man); void ManagedToNativeCopyTo(T man, IntPtr mem); void NativeFree(IntPtr nat); void NativeFreeInlistNodeElement(IntPtr nat); void NativeFreeInlistNode(IntPtr nat, bool freeElement); void NativeFreeInplace(IntPtr nat); void ResidueFreeInplace(IntPtr nat); T NativeToManaged(IntPtr nat); T NativeToManagedInlistNode(IntPtr nat); T NativeToManagedInplace(IntPtr nat); IntPtr EinaCompareCb(); IntPtr EinaFreeCb(); IntPtr EinaHashNew(); IntPtr EinaInarrayNew(uint step); IntPtr EinaHashIteratorKeyNew(IntPtr hash); } [EditorBrowsable(EditorBrowsableState.Never)] internal class StringElementTraits : IBaseElementTraits { public StringElementTraits() { } public IntPtr ManagedToNativeAlloc(string man) { IntPtr newstring = MemoryNative.StrDup(man); return newstring; } public IntPtr ManagedToNativeAllocInlistNode(string man) { var node = new InlistNode(); node.Val = ManagedToNativeAlloc(man); GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned); IntPtr ptr = pinnedData.AddrOfPinnedObject(); IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf() + Marshal.SizeOf()); pinnedData.Free(); return nat; } public void ManagedToNativeCopyTo(string man, IntPtr mem) { IntPtr stringptr = ManagedToNativeAlloc(man); Marshal.WriteIntPtr(mem, stringptr); } public void NativeFree(IntPtr nat) { if (nat != IntPtr.Zero) { MemoryNative.Free(nat); } } public void NativeFreeInlistNodeElement(IntPtr nat) { if (nat == IntPtr.Zero) { return; } var val = Marshal.PtrToStructure (nat + Marshal.SizeOf()); NativeFree(val); } public void NativeFreeInlistNode(IntPtr nat, bool freeElement) { if (nat == IntPtr.Zero) { return; } if (freeElement) { NativeFreeInlistNodeElement(nat); } MemoryNative.Free(nat); } public void NativeFreeInplace(IntPtr nat) { MemoryNative.FreeRef(nat); } public void ResidueFreeInplace(IntPtr nat) { } public string NativeToManaged(IntPtr nat) { if (nat == IntPtr.Zero) { return default(string); } return StringConversion.NativeUtf8ToManagedString(nat); } public string NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(string); } IntPtr ptr_location = nat + Marshal.SizeOf(); return NativeToManaged(Marshal.ReadIntPtr(ptr_location)); } // Strings inplaced are always a pointer, because they are variable-sized public string NativeToManagedInplace(IntPtr nat) { if (nat == IntPtr.Zero) { return default(string); } nat = Marshal.ReadIntPtr(nat); if (nat == IntPtr.Zero) { return default(string); } return NativeToManaged(nat); } public IntPtr EinaCompareCb() { return MemoryNative.StrCompareFuncPtrGet(); } public IntPtr EinaFreeCb() { return MemoryNative.FreeFuncPtrGet(); } public IntPtr EinaHashNew() { return eina_hash_string_superfast_new(IntPtr.Zero); } public IntPtr EinaInarrayNew(uint step) { return eina_inarray_new((uint)Marshal.SizeOf(), step); } public IntPtr EinaHashIteratorKeyNew(IntPtr hash) { return eina_hash_iterator_key_new(hash); } } [EditorBrowsable(EditorBrowsableState.Never)] internal class StringshareElementTraits : IBaseElementTraits { public StringshareElementTraits() { } public IntPtr ManagedToNativeAlloc(Eina.Stringshare man) { var strShare = MemoryNative.AddStringshare(man); return strShare; } public IntPtr ManagedToNativeAllocInlistNode(Eina.Stringshare man) { var node = new InlistNode(); node.Val = ManagedToNativeAlloc(man); GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned); IntPtr ptr = pinnedData.AddrOfPinnedObject(); IntPtr nat = MemoryNative.AllocCopy (ptr, Marshal.SizeOf() + Marshal.SizeOf()); pinnedData.Free(); return nat; } public void ManagedToNativeCopyTo(Eina.Stringshare man, IntPtr mem) { IntPtr stringptr = ManagedToNativeAlloc(man); Marshal.WriteIntPtr(mem, stringptr); } public void NativeFree(IntPtr nat) { if (nat != IntPtr.Zero) { MemoryNative.DelStringshare(nat); } } public void NativeFreeInlistNodeElement(IntPtr nat) { if (nat == IntPtr.Zero) { return; } var val = Marshal.PtrToStructure (nat + Marshal.SizeOf()); NativeFree(val); } public void NativeFreeInlistNode(IntPtr nat, bool freeElement) { if (nat == IntPtr.Zero) { return; } if (freeElement) { NativeFreeInlistNodeElement(nat); } MemoryNative.Free(nat); } public void NativeFreeInplace(IntPtr nat) { MemoryNative.DelStringshareRef(nat); } public void ResidueFreeInplace(IntPtr nat) { } public Eina.Stringshare NativeToManaged(IntPtr nat) { if (nat == IntPtr.Zero) { return default(Eina.Stringshare); } return StringConversion.NativeUtf8ToManagedString(nat); } public Eina.Stringshare NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(Eina.Stringshare); } IntPtr ptr_location = nat + Marshal.SizeOf(); return NativeToManaged(Marshal.ReadIntPtr(ptr_location)); } // Strings inplaced are always a pointer, because they are variable-sized public Eina.Stringshare NativeToManagedInplace(IntPtr nat) { if (nat == IntPtr.Zero) { return default(Eina.Stringshare); } nat = Marshal.ReadIntPtr(nat); if (nat == IntPtr.Zero) { return default(Eina.Stringshare); } return NativeToManaged(nat); } public IntPtr EinaCompareCb() { return MemoryNative.StrCompareFuncPtrGet(); } public IntPtr EinaFreeCb() { return MemoryNative.StringshareDelFuncPtrGet(); } public IntPtr EinaHashNew() { return eina_hash_stringshared_new(MemoryNative.StringshareDelFuncPtrGet()); } public IntPtr EinaInarrayNew(uint step) { return eina_inarray_new((uint)Marshal.SizeOf(), step); } public IntPtr EinaHashIteratorKeyNew(IntPtr hash) { return eina_hash_iterator_key_new(hash); } } [EditorBrowsable(EditorBrowsableState.Never)] internal class EflObjectElementTraits : IBaseElementTraits { public IntPtr ManagedToNativeAlloc(T man) { IntPtr h = ((Efl.Eo.IWrapper)man).NativeHandle; if (h == IntPtr.Zero) { return h; } return Efl.Eo.Globals.efl_ref(h); } public IntPtr ManagedToNativeAllocInlistNode(T man) { var node = new InlistNode(); node.Val = ManagedToNativeAlloc(man); GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned); IntPtr ptr = pinnedData.AddrOfPinnedObject(); IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf() + Marshal.SizeOf()); pinnedData.Free(); return nat; } public void ManagedToNativeCopyTo(T man, IntPtr mem) { IntPtr v = ManagedToNativeAlloc(man); Marshal.WriteIntPtr(mem, v); } public void NativeFree(IntPtr nat) { if (nat != IntPtr.Zero) { Efl.Eo.Globals.efl_mono_thread_safe_efl_unref(nat); } } public void NativeFreeRef(IntPtr nat, bool unrefs) { if (unrefs) { NativeFree(nat); } } public void NativeFreeInlistNodeElement(IntPtr nat) { if (nat == IntPtr.Zero) { return; } var val = Marshal.PtrToStructure (nat + Marshal.SizeOf()); NativeFree(val); } public void NativeFreeInlistNode(IntPtr nat, bool freeElement) { if (nat == IntPtr.Zero) { return; } if (freeElement) { NativeFreeInlistNodeElement(nat); } MemoryNative.Free(nat); } public void NativeFreeInplace(IntPtr nat) { NativeFree(nat); } public void ResidueFreeInplace(IntPtr nat) { } public T NativeToManaged(IntPtr nat) { if (nat == IntPtr.Zero) { return default(T); } return (T) Efl.Eo.Globals.CreateWrapperFor(nat, shouldIncRef: true); } public T NativeToManagedRef(IntPtr nat) { if (nat == IntPtr.Zero) { return default(T); } return NativeToManaged(nat); } public T NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(T); } IntPtr ptr_location = nat + Marshal.SizeOf(); return NativeToManaged(Marshal.ReadIntPtr(ptr_location)); } // EFL objects inplaced are always a pointer, because they are variable-sized public T NativeToManagedInplace(IntPtr nat) { if (nat == IntPtr.Zero) { return default(T); } nat = Marshal.ReadIntPtr(nat); if (nat == IntPtr.Zero) { return default(T); } return NativeToManaged(nat); } public IntPtr EinaCompareCb() { return MemoryNative.PtrCompareFuncPtrGet(); } public IntPtr EinaFreeCb() { return MemoryNative.EflUnrefFuncPtrGet(); } public IntPtr EinaHashNew() { return eina_hash_pointer_new(IntPtr.Zero); } public IntPtr EinaInarrayNew(uint step) { return eina_inarray_new((uint)Marshal.SizeOf(), step); } public IntPtr EinaHashIteratorKeyNew(IntPtr hash) { return eina_hash_iterator_ptr_key_wrapper_new_custom_export_mono(hash); } } [EditorBrowsable(EditorBrowsableState.Never)] internal abstract class PrimitiveElementTraits { private Eina.Callbacks.EinaCompareCb dlgt = null; public IntPtr ManagedToNativeAlloc(T man) { return PrimitiveConversion.ManagedToPointerAlloc(man); } public IntPtr ManagedToNativeAllocInlistNode(T man) { var node = new InlistNode(); node.Val = man; GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned); IntPtr ptr = pinnedData.AddrOfPinnedObject(); int Tsize = Marshal.SizeOf() < Marshal.SizeOf() ? Marshal.SizeOf() : Marshal.SizeOf(); IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf() + Tsize); pinnedData.Free(); return nat; } public void NativeFree(IntPtr nat) { MemoryNative.Free(nat); } public void NativeFreeInlistNodeElement(IntPtr nat) { // Do nothing } public void NativeFreeInlistNode(IntPtr nat, bool freeElement) { MemoryNative.Free(nat); } public void NativeFreeInplace(IntPtr nat) { // Do nothing } public void ResidueFreeInplace(IntPtr nat) { NativeFree(nat); } public T NativeToManaged(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer on primitive/struct container."); return default(T); } return PrimitiveConversion.PointerToManaged(nat); } public T NativeToManagedRef(IntPtr nat) { return NativeToManaged(nat); } public T NativeToManagedInplace(IntPtr nat) { return NativeToManaged(nat); } private int PrimitiveCompareCb(IntPtr ptr1, IntPtr ptr2) { var m1 = (IComparable)NativeToManaged(ptr1); var m2 = NativeToManaged(ptr2); return m1.CompareTo(m2); } public IntPtr EinaCompareCb() { if (dlgt == null) { dlgt = new Eina.Callbacks.EinaCompareCb(PrimitiveCompareCb); } return Marshal.GetFunctionPointerForDelegate(dlgt); } public IntPtr EinaFreeCb() { return MemoryNative.FreeFuncPtrGet(); } public IntPtr EinaInarrayNew(uint step) { return eina_inarray_new((uint)Marshal.SizeOf(), step); } public IntPtr EinaHashIteratorKeyNew(IntPtr hash) { return eina_hash_iterator_key_new(hash); } } [EditorBrowsable(EditorBrowsableState.Never)] internal abstract class Primitive32ElementTraits : PrimitiveElementTraits, IBaseElementTraits { private static IBaseElementTraits int32Traits = null; public Primitive32ElementTraits() { if (int32Traits == null) { if (typeof(T) == typeof(Int32)) // avoid infinite recursion { int32Traits = (IBaseElementTraits)this; } else { int32Traits = TraitFunctions.GetTypeTraits(); } } } public abstract void ManagedToNativeCopyTo(T man, IntPtr mem); public abstract T NativeToManagedInlistNode(IntPtr nat); public IntPtr ManagedToNativeAllocRef(T man, bool refs) { return int32Traits.ManagedToNativeAlloc(Convert.ToInt32((object)man, CultureInfo.CurrentCulture)); } public void NativeFreeRef(IntPtr nat, bool unrefs) { int32Traits.NativeFree(nat); } public IntPtr EinaHashNew() { return eina_hash_int32_new(IntPtr.Zero); } } [EditorBrowsable(EditorBrowsableState.Never)] internal abstract class Primitive64ElementTraits : PrimitiveElementTraits, IBaseElementTraits { private static IBaseElementTraits int64Traits = null; public Primitive64ElementTraits() { if (int64Traits == null) { if (typeof(T) == typeof(Int64)) // avoid infinite recursion { int64Traits = (IBaseElementTraits)this; } else { int64Traits = TraitFunctions.GetTypeTraits(); } } } public abstract void ManagedToNativeCopyTo(T man, IntPtr mem); public abstract T NativeToManagedInlistNode(IntPtr nat); public IntPtr ManagedToNativeAllocRef(T man, bool refs) { return int64Traits.ManagedToNativeAlloc(Convert.ToInt64((object)man, CultureInfo.CurrentCulture)); } public void NativeFreeRef(IntPtr nat, bool unrefs) { int64Traits.NativeFree(nat); } public IntPtr EinaHashNew() { return eina_hash_int64_new(IntPtr.Zero); } } [EditorBrowsable(EditorBrowsableState.Never)] internal class IntElementTraits : Primitive32ElementTraits, IBaseElementTraits { override public void ManagedToNativeCopyTo(int man, IntPtr mem) { var arr = new int[1]; arr[0] = man; Marshal.Copy(arr, 0, mem, 1); } override public int NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(int); } IntPtr loc = nat + Marshal.SizeOf(); var v = new int[1]; Marshal.Copy(loc, v, 0, 1); return v[0]; } } [EditorBrowsable(EditorBrowsableState.Never)] internal class CharElementTraits : Primitive32ElementTraits, IBaseElementTraits { override public void ManagedToNativeCopyTo(char man, IntPtr mem) { var arr = new char[1]; arr[0] = man; Marshal.Copy(arr, 0, mem, 1); } override public char NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(char); } IntPtr loc = nat + Marshal.SizeOf(); var v = new char[1]; Marshal.Copy(loc, v, 0, 1); return v[0]; } } [EditorBrowsable(EditorBrowsableState.Never)] internal class LongElementTraits : Primitive64ElementTraits, IBaseElementTraits { override public void ManagedToNativeCopyTo(long man, IntPtr mem) { var arr = new long[1]; arr[0] = man; Marshal.Copy(arr, 0, mem, 1); } override public long NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(long); } IntPtr loc = nat + Marshal.SizeOf(); var v = new long[1]; Marshal.Copy(loc, v, 0, 1); return v[0]; } } [EditorBrowsable(EditorBrowsableState.Never)] internal class ShortElementTraits : Primitive32ElementTraits, IBaseElementTraits { override public void ManagedToNativeCopyTo(short man, IntPtr mem) { var arr = new short[1]; arr[0] = man; Marshal.Copy(arr, 0, mem, 1); } override public short NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(short); } IntPtr loc = nat + Marshal.SizeOf(); var v = new short[1]; Marshal.Copy(loc, v, 0, 1); return v[0]; } } [EditorBrowsable(EditorBrowsableState.Never)] internal class FloatElementTraits : Primitive32ElementTraits, IBaseElementTraits { override public void ManagedToNativeCopyTo(float man, IntPtr mem) { var arr = new float[1]; arr[0] = man; Marshal.Copy(arr, 0, mem, 1); } override public float NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(float); } IntPtr loc = nat + Marshal.SizeOf(); var v = new float[1]; Marshal.Copy(loc, v, 0, 1); return v[0]; } } [EditorBrowsable(EditorBrowsableState.Never)] internal class DoubleElementTraits : Primitive64ElementTraits, IBaseElementTraits { override public void ManagedToNativeCopyTo(double man, IntPtr mem) { var arr = new double[1]; arr[0] = man; Marshal.Copy(arr, 0, mem, 1); } override public double NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(double); } IntPtr loc = nat + Marshal.SizeOf(); var v = new double[1]; Marshal.Copy(loc, v, 0, 1); return v[0]; } } [EditorBrowsable(EditorBrowsableState.Never)] internal class ByteElementTraits : Primitive32ElementTraits, IBaseElementTraits { override public void ManagedToNativeCopyTo(byte man, IntPtr mem) { var arr = new byte[1]; arr[0] = man; Marshal.Copy(arr, 0, mem, 1); } override public byte NativeToManagedInlistNode(IntPtr nat) { if (nat == IntPtr.Zero) { Eina.Log.Error("Null pointer for Inlist node."); return default(byte); } IntPtr loc = nat + Marshal.SizeOf(); var v = new byte[1]; Marshal.Copy(loc, v, 0, 1); return v[0]; } } [EditorBrowsable(EditorBrowsableState.Never)] internal static class TraitFunctions { public static bool IsEflObject(System.Type type) { return typeof(Efl.Eo.IWrapper).IsAssignableFrom(type); } public static bool IsString(System.Type type) { return type == typeof(string); } public static bool IsStringshare(System.Type type) { return type == typeof(Eina.Stringshare); } public static Eina.ElementType GetElementTypeCode(System.Type type) { if (IsEflObject(type)) { return ElementType.ObjectType; } else if (IsString(type)) { return ElementType.StringType; } else if (IsStringshare(type)) { return ElementType.StringshareType; } else { return ElementType.NumericType; } } private static IDictionary register = new Dictionary(); public static object RegisterTypeTraits() { Eina.Log.Debug($"Finding TypeTraits for {typeof(T).Name}"); object traits; var type = typeof(T); if (IsEflObject(type)) { traits = new EflObjectElementTraits(); } else if (IsString(type)) { traits = new StringElementTraits(); } else if (IsStringshare(type)) { traits = new StringshareElementTraits(); } else if (type.IsValueType) { if (type == typeof(int)) { traits = new IntElementTraits(); } else if (type == typeof(char)) { traits = new CharElementTraits(); } else if (type == typeof(long)) { traits = new LongElementTraits(); } else if (type == typeof(short)) { traits = new ShortElementTraits(); } else if (type == typeof(float)) { traits = new FloatElementTraits(); } else if (type == typeof(double)) { traits = new DoubleElementTraits(); } else if (type == typeof(byte)) { traits = new ByteElementTraits(); } else { throw new Exception("No traits registered for this type"); } } else { throw new Exception("No traits registered for this type"); } register[type] = traits; return traits; } public static object RegisterTypeTraits(IBaseElementTraits traits) { register[typeof(T)] = traits; return traits; } public static IBaseElementTraits GetTypeTraits() { object traits; if (!register.TryGetValue(typeof(T), out traits)) { traits = RegisterTypeTraits(); } return (IBaseElementTraits)traits; } // // // Traits functions // // // // Convertion functions // public static IntPtr ManagedToNativeAlloc(T man) { return GetTypeTraits().ManagedToNativeAlloc(man); } public static void ManagedToNativeCopyTo(T man, IntPtr mem) { GetTypeTraits().ManagedToNativeCopyTo(man, mem); } public static IntPtr ManagedToNativeAllocInlistNode(T man) { return GetTypeTraits().ManagedToNativeAllocInlistNode(man); } public static void NativeFree(IntPtr nat) { GetTypeTraits().NativeFree(nat); } public static void NativeFreeInlistNodeElement(IntPtr nat) { GetTypeTraits().NativeFreeInlistNodeElement(nat); } public static void NativeFreeInlistNode(IntPtr nat, bool freeElement = true) { GetTypeTraits().NativeFreeInlistNode(nat, freeElement); } public static void NativeFreeInplace(IntPtr nat) { GetTypeTraits().NativeFreeInplace(nat); } public static void ResidueFreeInplace(IntPtr nat) { GetTypeTraits().ResidueFreeInplace(nat); } public static T NativeToManaged(IntPtr nat) { return GetTypeTraits().NativeToManaged(nat); } public static T NativeToManagedInlistNode(IntPtr nat) { return GetTypeTraits().NativeToManagedInlistNode(nat); } public static T NativeToManagedInplace(IntPtr nat) { return GetTypeTraits().NativeToManagedInplace(nat); } // Misc // public static IntPtr EinaCompareCb() { return GetTypeTraits().EinaCompareCb(); } public static IntPtr EinaFreeCb() { return GetTypeTraits().EinaFreeCb(); } public static IntPtr EinaHashNew() { return GetTypeTraits().EinaHashNew(); } public static IntPtr EinaInarrayNew(uint step) { return GetTypeTraits().EinaInarrayNew(step); } public static IntPtr EinaHashIteratorKeyNew(IntPtr hash) { return GetTypeTraits().EinaHashIteratorKeyNew(hash); } } }