prog
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
This commit is contained in:
@@ -40,6 +40,7 @@ namespace FlaxEngine.Interop
|
||||
object managed = ManagedHandle.FromIntPtr(unmanaged).Target;
|
||||
if (managed is ManagedArray managedArray)
|
||||
{
|
||||
throw new Exception("not supported");
|
||||
var managedArrayHandle = ManagedHandle.Alloc(managedArray, GCHandleType.Normal);
|
||||
managed = NativeInterop.MarshalToManaged((IntPtr)managedArrayHandle, managedArray.ArrayType);
|
||||
managedArrayHandle.Free();
|
||||
|
||||
@@ -807,8 +807,11 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
// The internal exception thrown in MethodInfo.Invoke is caught here
|
||||
Exception realException = exception;
|
||||
if (exception.InnerException != null && exception.TargetSite.ReflectedType.Name == "MethodInvoker")
|
||||
if (exception.InnerException != null &&
|
||||
(exception.TargetSite.ReflectedType.Name == "MethodInvoker" || exception.TargetSite.ReflectedType.Name == "MethodBaseInvoker"))
|
||||
{
|
||||
realException = exception.InnerException;
|
||||
}
|
||||
|
||||
if (exceptionPtr != IntPtr.Zero)
|
||||
Unsafe.Write<IntPtr>(exceptionPtr.ToPointer(), ManagedHandle.ToIntPtr(realException, GCHandleType.Weak));
|
||||
|
||||
@@ -21,6 +21,7 @@ using System.Threading;
|
||||
using System.Buffers;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
using FlaxEngine.Utilities;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace FlaxEngine.Interop
|
||||
{
|
||||
@@ -412,7 +413,86 @@ namespace FlaxEngine.Interop
|
||||
internal static ConcurrentDictionary<Type, MarshalToNativeDelegate> toNativeMarshallers = new ConcurrentDictionary<Type, MarshalToNativeDelegate>(1, 3);
|
||||
internal static ConcurrentDictionary<Type, MarshalToNativeFieldDelegate> toNativeFieldMarshallers = new ConcurrentDictionary<Type, MarshalToNativeFieldDelegate>(1, 3);
|
||||
|
||||
internal static ConcurrentDictionary<Type, (Type, Func<object, object>)> _marshallers = new(1, 3);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
internal static ConcurrentDictionary<Type, (Type, Func<object, object>, Func<IntPtr, object>)> _marshallers = new(1, 3);
|
||||
|
||||
internal static class NewMarshalHelperValueType<TDest, TSource> where TSource : struct
|
||||
{
|
||||
internal static object NativeToManaged9(object src)
|
||||
{
|
||||
return NewMarshalHelper<TDest, TSource>.NativeToManaged9(ref Unsafe.Unbox<TSource>(src));
|
||||
}
|
||||
}
|
||||
|
||||
internal static class NewMarshalHelperReferenceType<TDest, TSource> where TSource : class
|
||||
{
|
||||
internal static object NativeToManaged9(object src)
|
||||
{
|
||||
TSource tsrc = Unsafe.As<TSource>(src);
|
||||
return NewMarshalHelper<TDest, TSource>.NativeToManaged9(ref tsrc);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class NewMarshalHelper<TDest, TSource>
|
||||
{
|
||||
internal static Func<TSource, TDest> _nativeToManagedFunc;
|
||||
internal static Type _pointerType;
|
||||
|
||||
internal static void Init(MethodInfo nativeToManagedMethod)
|
||||
{
|
||||
//Assert.IsNull(_nativeToManagedFunc);
|
||||
|
||||
//var internalType = nativeToManagedMethod.GetParameters()[0].ParameterType;
|
||||
//var types = new Type[] { marshalType, internalType };
|
||||
//var convertDelegate = method.CreateDelegate(typeof(ToManagedDelegate<,>).MakeGenericType(types));
|
||||
|
||||
if (_nativeToManagedFunc == null && nativeToManagedMethod != null)
|
||||
_nativeToManagedFunc = nativeToManagedMethod.CreateDelegate<Func<TSource, TDest>>();
|
||||
|
||||
_pointerType = typeof(TDest).MakePointerType();
|
||||
}
|
||||
|
||||
internal static TDest NativeToManaged9(ref TSource src)
|
||||
{
|
||||
return _nativeToManagedFunc(src);
|
||||
}
|
||||
|
||||
internal static object NativeToManagedIntPtr(TSource src)
|
||||
{
|
||||
// typeof(TSource) == typeof(IntPtr)
|
||||
return _nativeToManagedFunc(src);
|
||||
}
|
||||
|
||||
internal static object NativeToManagedPointer(IntPtr src)
|
||||
{
|
||||
//byte* asd = null;
|
||||
//return asd;
|
||||
return Pointer.Box(src.ToPointer(), _pointerType);
|
||||
}
|
||||
|
||||
internal static object NativeToManagedByPass(TSource src) => src;
|
||||
|
||||
internal static object NativeToManaged(IntPtr src)
|
||||
{
|
||||
// typeof(TSource) != typeof(IntPtr)
|
||||
TSource native = Marshal.PtrToStructure<TSource>(src);
|
||||
return _nativeToManagedFunc(native);
|
||||
}
|
||||
|
||||
internal static object NativeToManagedDirect(IntPtr src)
|
||||
{
|
||||
// typeof(TSource) != typeof(IntPtr)
|
||||
TSource native = Unsafe.Read<TSource>(src.ToPointer());
|
||||
return native;
|
||||
}
|
||||
}
|
||||
|
||||
internal static object MarshalToManaged2(IntPtr nativePtr, Type type)
|
||||
{
|
||||
@@ -432,6 +512,10 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
if (type == typeof(bool))
|
||||
return typeof(BooleanMarshaller);
|
||||
else if (type == typeof(string))
|
||||
return typeof(StringMarshaller); // UTF-16 strings via MMethod::Invoke
|
||||
else if (type == typeof(object))
|
||||
return typeof(AsManagedHandleMarshaller);
|
||||
else if (type.IsArray)
|
||||
return null;
|
||||
|
||||
@@ -441,12 +525,13 @@ namespace FlaxEngine.Interop
|
||||
|
||||
return marshallerType;
|
||||
}
|
||||
static (Type, Func<object, object>) Factory2(Type type)
|
||||
static (Type, Func<object, object>, Func<IntPtr, object>) Factory2(Type type)
|
||||
{
|
||||
Type marshalType = type;
|
||||
if (marshalType.IsByRef)
|
||||
marshalType = marshalType.GetElementType();
|
||||
else if (marshalType == typeof(byte*) || marshalType == typeof(char*))
|
||||
|
||||
if (marshalType == typeof(byte*) || marshalType == typeof(char*))
|
||||
{
|
||||
}
|
||||
else if (marshalType.IsPointer)
|
||||
@@ -473,17 +558,63 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
if (marshalType == typeof(IntPtr))
|
||||
{
|
||||
//var setup = typeof(NewMarshalHelper<,>).MakeGenericType([typeof(IntPtr), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.Init), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
//setup.Invoke(null, [method]);
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType([typeof(IntPtr), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedByPass), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
|
||||
Func<object, object> func = (obj) => obj;
|
||||
return (typeof(IntPtr), func);
|
||||
return (typeof(IntPtr), func, convdirectdel);
|
||||
}
|
||||
else if (marshalType == typeof(ManagedHandle))
|
||||
{
|
||||
var methody = typeof(ManagedHandle).GetMethod(nameof(ManagedHandle.FromIntPtr), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var setup = typeof(NewMarshalHelper<,>).MakeGenericType([typeof(ManagedHandle), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.Init), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
setup.Invoke(null, [methody]);
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType([typeof(ManagedHandle), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedIntPtr), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
|
||||
Func<object, object> func = (obj) => ManagedHandle.FromIntPtr((IntPtr)obj);
|
||||
return (typeof(IntPtr), func);
|
||||
return (typeof(IntPtr), func, convdirectdel);
|
||||
}
|
||||
else if (marshalType.IsPointer)
|
||||
{
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType([typeof(IntPtr), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedDirect), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
|
||||
Func<object, object> func = (obj) => obj;
|
||||
return (typeof(IntPtr), func, convdirectdel);
|
||||
//return (null, null, null);
|
||||
/*var setup = typeof(NewMarshalHelper<,>).MakeGenericType([marshalType.GetElementType(), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.Init), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
setup.Invoke(null, [null]);
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType([marshalType.GetElementType(), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedPointer), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
return (marshalType, null, convdirectdel);*/
|
||||
}
|
||||
else if (marshalType.IsPrimitive || marshalType.IsEnum)
|
||||
{
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType([marshalType, marshalType]).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedDirect), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
return (marshalType, null, convdirectdel);
|
||||
}
|
||||
else if (!marshalType.IsArray && IsBlittable(marshalType))
|
||||
{
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType([marshalType, marshalType]).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedDirect), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
return (marshalType, null, convdirectdel);
|
||||
}
|
||||
|
||||
/*else if (marshalType == typeof(object))
|
||||
{
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType([typeof(ManagedHandle), typeof(IntPtr)]).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedIntPtr), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
|
||||
Func<object, object> func = (obj) => (IntPtr)obj != IntPtr.Zero ? ManagedHandle.FromIntPtr((IntPtr)obj).Target : null;
|
||||
return (typeof(IntPtr), func, null);
|
||||
}*/
|
||||
}
|
||||
if (marshallerType == null)
|
||||
return (null, null);
|
||||
return (null, null, null);
|
||||
|
||||
MethodInfo method = marshallerType.GetMethod("ConvertToManaged", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
if (method == null)
|
||||
@@ -502,71 +633,116 @@ namespace FlaxEngine.Interop
|
||||
}
|
||||
}
|
||||
|
||||
return (null, null);
|
||||
return (null, null, null);
|
||||
}
|
||||
|
||||
var internalType = method.GetParameters()[0].ParameterType;
|
||||
var types = new Type[] { marshalType, internalType };
|
||||
var convertDelegate = method.CreateDelegate(typeof(ToManagedDelegate<,>).MakeGenericType(types));
|
||||
if (internalType.IsStructure())
|
||||
|
||||
var minit = typeof(NewMarshalHelper<,>).MakeGenericType(types).GetMethod(nameof(NewMarshalHelper<,>.Init), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
minit.Invoke(null, [method]);
|
||||
var conv = typeof(NewMarshalHelper<,>).MakeGenericType(types).GetMethod(nameof(NewMarshalHelper<,>.NativeToManaged), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdel = conv.CreateDelegate<Func<IntPtr, object>>();
|
||||
|
||||
|
||||
if (internalType == typeof(IntPtr))
|
||||
{
|
||||
var convdirect = typeof(NewMarshalHelper<,>).MakeGenericType(types).GetMethod(nameof(NewMarshalHelper<,>.NativeToManagedIntPtr), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var convdirectdel = convdirect.CreateDelegate<Func<IntPtr, object>>();
|
||||
|
||||
Func<object, object> func =
|
||||
(obj) => convertDelegate.DynamicInvoke(obj);
|
||||
|
||||
return (internalType, func, convdirectdel);
|
||||
}
|
||||
else if (internalType.IsStructure())
|
||||
{
|
||||
Func<object, object> func =
|
||||
(obj) => convertDelegate.DynamicInvoke(obj);
|
||||
return (internalType, func);
|
||||
|
||||
return (internalType, func, convdel);
|
||||
}
|
||||
else
|
||||
{
|
||||
Func<object, object> func =
|
||||
(obj) => convertDelegate.DynamicInvoke(obj);
|
||||
return (internalType, func);
|
||||
return (internalType, func, convdel);
|
||||
}
|
||||
}
|
||||
|
||||
var type2 = type.IsByRef ? type.GetElementType() : type;
|
||||
/*if (type2.IsPrimitive)
|
||||
{
|
||||
if (type.IsByRef && type2 == typeof(IntPtr))
|
||||
nativePtr = Unsafe.Read<IntPtr>(nativePtr.ToPointer());
|
||||
|
||||
//ref byte src = ref Unsafe.AsRef<byte>(nativePtr.ToPointer());
|
||||
//var ret = RuntimeHelpers.Box(ref src, type.TypeHandle);
|
||||
var ret = Marshal.PtrToStructure(nativePtr, type2);
|
||||
return ret;
|
||||
}
|
||||
else if (type2.IsEnum)
|
||||
{
|
||||
if (type.IsByRef)
|
||||
type2 = type2;
|
||||
ref byte src = ref Unsafe.AsRef<byte>(nativePtr.ToPointer());
|
||||
var ret = RuntimeHelpers.Box(ref src, type2.TypeHandle);
|
||||
return ret;
|
||||
}*/
|
||||
if (!_marshallers.TryGetValue(type, out var marsh))
|
||||
marsh = _marshallers.GetOrAdd(type, Factory2);
|
||||
if (!toManagedMarshallers.TryGetValue(type, out var deleg))
|
||||
deleg = toManagedMarshallers.GetOrAdd(type, Factory);
|
||||
|
||||
if (marsh.Item2 != null)
|
||||
{
|
||||
object conv1 = deleg(nativePtr, type.IsByRef && false);
|
||||
if (type.IsByRef && marsh.Item1 == typeof(IntPtr))
|
||||
nativePtr = Unsafe.Read<IntPtr>(nativePtr.ToPointer());
|
||||
object value = marsh.Item1 == typeof(IntPtr) ? nativePtr : Marshal.PtrToStructure(nativePtr, marsh.Item1);//Unsafe.Read<byte>(nativePtr.ToPointer());
|
||||
object conv2 = marsh.Item2(value);
|
||||
if (conv1 is null && conv2 is null)
|
||||
{ }
|
||||
else if (!conv1.Equals(conv2))
|
||||
Assert.IsTrue(conv1.Equals(conv2));
|
||||
return conv2;
|
||||
}
|
||||
else if (type2 == typeof(bool))
|
||||
if (marsh.Item3 != null)
|
||||
{
|
||||
//object conv1 = deleg(nativePtr, type.IsByRef && false);
|
||||
byte value = Unsafe.Read<byte>(nativePtr.ToPointer());
|
||||
object conv2 = BooleanMarshaller.ConvertToManaged(value);
|
||||
//Assert.IsTrue(conv1.Equals(conv2));
|
||||
return conv2;
|
||||
}
|
||||
else if (type2 == typeof(ManagedHandle))
|
||||
{
|
||||
//ManagedHandle conv1 = (ManagedHandle)deleg(nativePtr, type.IsByRef && false);
|
||||
ManagedHandle conv2 = ManagedHandle.FromIntPtr(nativePtr);
|
||||
//Assert.IsTrue(conv1.Equals(conv2));
|
||||
return conv2;
|
||||
}
|
||||
else if (type2 == typeof(int) || type2.IsEnum ||
|
||||
type2 == typeof(IntPtr) || type2 == typeof(Float2) || type2 == typeof(Float3) || type2 == typeof(Guid))
|
||||
{
|
||||
if (type.IsByRef && marsh.Item1 == typeof(IntPtr))
|
||||
nativePtr = Unsafe.Read<IntPtr>(nativePtr.ToPointer());
|
||||
if (true && marsh.Item3 != null)
|
||||
{
|
||||
// TODO: CustomMarshaller.Free()
|
||||
return marsh.Item3(nativePtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
object value = marsh.Item1 == typeof(IntPtr) ? nativePtr : Marshal.PtrToStructure(nativePtr, marsh.Item1);
|
||||
object conv2 = marsh.Item2(value);
|
||||
|
||||
// TODO: CustomMarshaller.Free()
|
||||
return conv2;
|
||||
}
|
||||
/*if (conv1 is null && conv2 is null)
|
||||
{ }
|
||||
else if (!conv1.Equals(conv2))
|
||||
Assert.IsTrue(conv1.Equals(conv2));*/
|
||||
|
||||
|
||||
}
|
||||
if (type2.IsStructure())
|
||||
{
|
||||
var ret = Marshal.PtrToStructure(nativePtr, type2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if (type2 == typeof(int) || type2.IsEnum
|
||||
|| type2 == typeof(IntPtr) || type2 == typeof(Float2) || type2 == typeof(Float3)
|
||||
|| type2 == typeof(long) || type2 == typeof(sbyte)
|
||||
|| type2 == typeof(uint) || type2 == typeof(ulong) || type2 == typeof(ushort) || type2 == typeof(byte)
|
||||
|| type2 == typeof(float) || type2 == typeof(double))
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else if (type2 == typeof(byte*) || type2 == typeof(Guid) || type2.IsArray)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!toManagedMarshallers.TryGetValue(type, out var deleg))
|
||||
deleg = toManagedMarshallers.GetOrAdd(type, Factory);
|
||||
return deleg(nativePtr, type.IsByRef && false);
|
||||
}
|
||||
|
||||
@@ -1640,7 +1816,8 @@ namespace FlaxEngine.Interop
|
||||
|
||||
internal static void ToNativeString(ref string managedValue, IntPtr nativePtr)
|
||||
{
|
||||
Unsafe.Write<IntPtr>(nativePtr.ToPointer(), ManagedString.ToNative/*Weak*/(managedValue));
|
||||
//Unsafe.Write<IntPtr>(nativePtr.ToPointer(), ManagedString.ToNative/*Weak*/(managedValue));
|
||||
Unsafe.Write<NativeString>(nativePtr.ToPointer(), new NativeString(managedValue));
|
||||
}
|
||||
|
||||
internal static void ToNativeType(ref Type managedValue, IntPtr nativePtr)
|
||||
|
||||
Reference in New Issue
Block a user