From daa92db25c169dc30feb050d1bb846bf8a147a02 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 12 Jan 2023 15:14:43 +0100 Subject: [PATCH] Add support for using managed method thunks on dotnet7 in all cases --- Source/Engine/Engine/NativeInterop.cs | 88 +++++----- Source/Engine/Engine/NativeInterop_Invoker.cs | 156 ++++++++++++------ Source/Engine/Utilities/Utils.cs | 20 +++ .../Bindings/BindingsGenerator.Cpp.cs | 2 +- 4 files changed, 175 insertions(+), 91 deletions(-) diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index ec1869fe6..967503c51 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -1405,6 +1405,7 @@ namespace FlaxEngine toManagedTypedMarshaller(ref managedValue, nativePtr, byRef); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T ToManagedUnbox(IntPtr nativePtr) { T managed = default; @@ -1774,7 +1775,7 @@ namespace FlaxEngine internal MethodHolder(MethodInfo method) { this.method = method; - parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray(); + parameterTypes = method.GetParameterTypes(); } internal bool TryGetDelegate(out Invoker.MarshalAndInvokeDelegate outDeleg, out object outDelegInvoke) @@ -2394,26 +2395,8 @@ namespace FlaxEngine } } - if (returnObject is not null) - { - if (methodHolder.method.ReturnType == typeof(string)) - return ManagedString.ToNative(Unsafe.As(returnObject)); - else if (methodHolder.method.ReturnType == typeof(IntPtr)) - return (IntPtr)returnObject; - else if (methodHolder.method.ReturnType == typeof(ManagedHandle)) - return ManagedHandle.ToIntPtr((ManagedHandle)(object)returnObject); - else if (methodHolder.method.ReturnType == typeof(bool)) - return (bool)returnObject ? boolTruePtr : boolFalsePtr; - else if (methodHolder.method.ReturnType == typeof(Type)) - return ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnObject))); - else if (methodHolder.method.ReturnType.IsArray && ArrayFactory.GetMarshalledType(methodHolder.method.ReturnType.GetElementType()) == methodHolder.method.ReturnType.GetElementType()) - return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(Unsafe.As(returnObject)), GCHandleType.Weak)); - else if (methodHolder.method.ReturnType.IsArray) - return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnObject))), GCHandleType.Weak)); - else - return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnObject, GCHandleType.Weak)); - } - return IntPtr.Zero; + // Return value + return Invoker.MarshalReturnValueGeneric(methodHolder.method.ReturnType, returnObject); } } @@ -2953,7 +2936,14 @@ namespace FlaxEngine internal ThunkContext(MethodInfo method) { this.method = method; - parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray(); + parameterTypes = method.GetParameterTypes(); + + // Thunk delegates don't support IsByRef parameters (use egenric invocation for now) + foreach (var type in parameterTypes) + { + if (type.IsByRef) + return; + } List methodTypes = new List(); if (!method.IsStatic) @@ -3014,7 +3004,25 @@ namespace FlaxEngine int numParams = parameterTypes.Length; object[] methodParameters = new object[numParams]; for (int i = 0; i < numParams; i++) - methodParameters[i] = nativePtrs[i] == IntPtr.Zero ? null : ManagedHandle.FromIntPtr(nativePtrs[i]).Target; + { + IntPtr nativePtr = nativePtrs[i]; + object managed = null; + if (nativePtr != IntPtr.Zero) + { + Type type = parameterTypes[i]; + Type elementType = type.GetElementType(); + if (type.IsByRef && !elementType.IsValueType) + { + nativePtr = Marshal.ReadIntPtr(nativePtr); + type = elementType; + } + if (type.IsArray) + managed = MarshalToManaged(nativePtr, type); // Array might be in internal format of custom structs so unbox if need to + else + managed = ManagedHandle.FromIntPtr(nativePtr).Target; + } + methodParameters[i] = managed; + } try { @@ -3029,24 +3037,26 @@ namespace FlaxEngine return IntPtr.Zero; } - if (returnObject is not null) + // Marshal reference parameters back to original unmanaged references + for (int i = 0; i < numParams; i++) { - if (method.ReturnType == typeof(string)) - return ManagedString.ToNative(Unsafe.As(returnObject)); - else if (method.ReturnType == typeof(IntPtr)) - return (IntPtr)returnObject; - else if (method.ReturnType == typeof(ManagedHandle)) - return ManagedHandle.ToIntPtr((ManagedHandle)returnObject); - else if (method.ReturnType == typeof(bool)) - return (bool)returnObject ? boolTruePtr : boolFalsePtr; - else if (method.ReturnType == typeof(Type)) - return ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnObject))); - else if (method.ReturnType == typeof(object[])) - return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnObject))), GCHandleType.Weak)); - else - return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnObject, GCHandleType.Weak)); + IntPtr nativePtr = nativePtrs[i]; + Type type = parameterTypes[i]; + Type elementType = type.GetElementType(); + if (nativePtr != IntPtr.Zero && type.IsByRef) + { + if (elementType.IsValueType) + { + // Return directly to the original value + var ęxistingValue = ManagedHandle.FromIntPtr(nativePtr).Target; + nativePtr = ValueTypeUnboxer.GetPointer(ęxistingValue); + } + MarshalToNative(methodParameters[i], nativePtr, elementType); + } } - return IntPtr.Zero; + + // Return value + return Invoker.MarshalReturnValueThunkGeneric(method.ReturnType, returnObject); } } } diff --git a/Source/Engine/Engine/NativeInterop_Invoker.cs b/Source/Engine/Engine/NativeInterop_Invoker.cs index eb8925d2b..39d080ff1 100644 --- a/Source/Engine/Engine/NativeInterop_Invoker.cs +++ b/Source/Engine/Engine/NativeInterop_Invoker.cs @@ -38,7 +38,7 @@ namespace FlaxEngine { Type[] methodParameters; if (method.IsStatic) - methodParameters = method.GetParameters().Select(x => x.ParameterType).ToArray(); + methodParameters = method.GetParameterTypes(); else methodParameters = method.GetParameters().Select(x => x.ParameterType).Prepend(method.DeclaringType).ToArray(); @@ -75,67 +75,121 @@ namespace FlaxEngine internal static IntPtr MarshalReturnValue(ref TRet returnValue) { + if (returnValue == null) + return IntPtr.Zero; if (typeof(TRet) == typeof(string)) return ManagedString.ToNative(Unsafe.As(returnValue)); - else if (typeof(TRet) == typeof(IntPtr)) + if (typeof(TRet) == typeof(IntPtr)) return (IntPtr)(object)returnValue; - else if (typeof(TRet) == typeof(ManagedHandle)) + if (typeof(TRet) == typeof(ManagedHandle)) return ManagedHandle.ToIntPtr((ManagedHandle)(object)returnValue); - else if (typeof(TRet) == typeof(bool)) + if (typeof(TRet) == typeof(bool)) return (bool)(object)returnValue ? boolTruePtr : boolFalsePtr; - else if (typeof(TRet) == typeof(Type)) - return returnValue != null ? ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnValue))) : IntPtr.Zero; - else if (typeof(TRet).IsArray) + if (typeof(TRet) == typeof(Type)) + return ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnValue))); + if (typeof(TRet).IsArray) { - if (returnValue == null) - return IntPtr.Zero; var elementType = typeof(TRet).GetElementType(); if (ArrayFactory.GetMarshalledType(elementType) == elementType) return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(Unsafe.As(returnValue)), GCHandleType.Weak)); - else - return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnValue))), GCHandleType.Weak)); + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnValue))), GCHandleType.Weak)); } - else - return returnValue != null ? ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnValue, GCHandleType.Weak)) : IntPtr.Zero; + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnValue, GCHandleType.Weak)); + } + + internal static IntPtr MarshalReturnValueGeneric(Type returnType, object returnObject) + { + if (returnObject == null) + return IntPtr.Zero; + if (returnType == typeof(string)) + return ManagedString.ToNative(Unsafe.As(returnObject)); + if (returnType == typeof(IntPtr)) + return (IntPtr)returnObject; + if (returnType == typeof(ManagedHandle)) + return ManagedHandle.ToIntPtr((ManagedHandle)(object)returnObject); + if (returnType == typeof(bool)) + return (bool)returnObject ? boolTruePtr : boolFalsePtr; + if (returnType == typeof(Type)) + return ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnObject))); + if (returnType.IsArray && ArrayFactory.GetMarshalledType(returnType.GetElementType()) == returnType.GetElementType()) + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(Unsafe.As(returnObject)), GCHandleType.Weak)); + if (returnType.IsArray) + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnObject))), GCHandleType.Weak)); + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnObject, GCHandleType.Weak)); } internal static IntPtr MarshalReturnValueThunk(ref TRet returnValue) { + if (returnValue == null) + return IntPtr.Zero; if (typeof(TRet) == typeof(string)) return ManagedString.ToNative(Unsafe.As(returnValue)); - else if (typeof(TRet) == typeof(IntPtr)) + if (typeof(TRet) == typeof(IntPtr)) return (IntPtr)(object)returnValue; - else if (typeof(TRet) == typeof(ManagedHandle)) + if (typeof(TRet) == typeof(ManagedHandle)) return ManagedHandle.ToIntPtr((ManagedHandle)(object)returnValue); - else if (typeof(TRet) == typeof(Type)) - return returnValue != null ? ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnValue))) : IntPtr.Zero; - else if (typeof(TRet).IsArray) + if (typeof(TRet) == typeof(Type)) + return ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnValue))); + if (typeof(TRet).IsArray) { - if (returnValue == null) - return IntPtr.Zero; var elementType = typeof(TRet).GetElementType(); if (ArrayFactory.GetMarshalledType(elementType) == elementType) return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(Unsafe.As(returnValue)), GCHandleType.Weak)); - else - return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnValue))), GCHandleType.Weak)); + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnValue))), GCHandleType.Weak)); } // Match Mono bindings and pass value as pointer to prevent boxing it - else if (typeof(TRet) == typeof(System.Boolean)) + if (typeof(TRet) == typeof(System.Boolean)) return new IntPtr(((System.Boolean)(object)returnValue) ? 1 : 0); - else if (typeof(TRet) == typeof(System.Int16)) + if (typeof(TRet) == typeof(System.Int16)) return new IntPtr((int)(System.Int16)(object)returnValue); - else if (typeof(TRet) == typeof(System.Int32)) + if (typeof(TRet) == typeof(System.Int32)) return new IntPtr((int)(System.Int32)(object)returnValue); - else if (typeof(TRet) == typeof(System.Int64)) + if (typeof(TRet) == typeof(System.Int64)) return new IntPtr((long)(System.Int64)(object)returnValue); - else if (typeof(TRet) == typeof(System.UInt16)) + if (typeof(TRet) == typeof(System.UInt16)) return (IntPtr)new UIntPtr((ulong)(System.UInt16)(object)returnValue); - else if (typeof(TRet) == typeof(System.UInt32)) + if (typeof(TRet) == typeof(System.UInt32)) return (IntPtr)new UIntPtr((ulong)(System.UInt32)(object)returnValue); - else if (typeof(TRet) == typeof(System.UInt64)) + if (typeof(TRet) == typeof(System.UInt64)) return (IntPtr)new UIntPtr((ulong)(System.UInt64)(object)returnValue); - else - return returnValue != null ? ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnValue, GCHandleType.Weak)) : IntPtr.Zero; + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnValue, GCHandleType.Weak)); + } + + internal static IntPtr MarshalReturnValueThunkGeneric(Type returnType, object returnObject) + { + if (returnObject == null) + return IntPtr.Zero; + if (returnType == typeof(string)) + return ManagedString.ToNative(Unsafe.As(returnObject)); + if (returnType == typeof(IntPtr)) + return (IntPtr)(object)returnObject; + if (returnType == typeof(ManagedHandle)) + return ManagedHandle.ToIntPtr((ManagedHandle)(object)returnObject); + if (returnType == typeof(Type)) + return returnObject != null ? ManagedHandle.ToIntPtr(GetTypeGCHandle(Unsafe.As(returnObject))) : IntPtr.Zero; + if (returnType.IsArray) + { + var elementType = returnType.GetElementType(); + if (ArrayFactory.GetMarshalledType(elementType) == elementType) + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(Unsafe.As(returnObject)), GCHandleType.Weak)); + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As(returnObject))), GCHandleType.Weak)); + } + // Match Mono bindings and pass value as pointer to prevent boxing it + if (returnType == typeof(System.Boolean)) + return new IntPtr(((System.Boolean)(object)returnObject) ? 1 : 0); + if (returnType == typeof(System.Int16)) + return new IntPtr((int)(System.Int16)(object)returnObject); + if (returnType == typeof(System.Int32)) + return new IntPtr((int)(System.Int32)(object)returnObject); + if (returnType == typeof(System.Int64)) + return new IntPtr((long)(System.Int64)(object)returnObject); + if (returnType == typeof(System.UInt16)) + return (IntPtr)new UIntPtr((ulong)(System.UInt16)(object)returnObject); + if (returnType == typeof(System.UInt32)) + return (IntPtr)new UIntPtr((ulong)(System.UInt32)(object)returnObject); + if (returnType == typeof(System.UInt64)) + return (IntPtr)new UIntPtr((ulong)(System.UInt64)(object)returnObject); + return ManagedHandle.ToIntPtr(ManagedHandle.Alloc(returnObject, GCHandleType.Weak)); } internal static class InvokerNoRet0 @@ -145,7 +199,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -181,7 +235,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -227,7 +281,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -278,7 +332,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -334,7 +388,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -395,7 +449,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -431,7 +485,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -477,7 +531,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -528,7 +582,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -584,7 +638,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -645,7 +699,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -681,7 +735,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -727,7 +781,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -778,7 +832,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -834,7 +888,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -895,7 +949,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -931,7 +985,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -977,7 +1031,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -1028,7 +1082,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) @@ -1084,7 +1138,7 @@ namespace FlaxEngine internal static object CreateDelegate(MethodInfo method) { - return new Tuple(method.GetParameters().Select(x => x.ParameterType).ToArray(), Unsafe.As(CreateDelegateFromMethod(method))); + return new Tuple(method.GetParameterTypes(), Unsafe.As(CreateDelegateFromMethod(method))); } internal static object CreateInvokerDelegate(MethodInfo method) diff --git a/Source/Engine/Utilities/Utils.cs b/Source/Engine/Utilities/Utils.cs index d1feaee7d..c7f2dc70a 100644 --- a/Source/Engine/Utilities/Utils.cs +++ b/Source/Engine/Utilities/Utils.cs @@ -1006,5 +1006,25 @@ namespace FlaxEngine } } } + + /// + /// Gets the array of method parameter types. + /// + /// The method to get it's parameters. + /// Method parameters array. + public static Type[] GetParameterTypes(this MethodInfo method) + { + Type[] parameterTypes; + var parameters = method.GetParameters(); + if (parameters.Length != 0) + { + parameterTypes = new Type[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + parameterTypes[i] = parameters[i].ParameterType; + } + else + parameterTypes = Array.Empty(); + return parameterTypes; + } } } diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs index 22fd5b5bf..3f0e92aaf 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs @@ -1342,7 +1342,7 @@ namespace Flax.Build.Bindings // If platform supports JITed code execution then use method thunk, otherwise fallback to generic mono_runtime_invoke var returnType = functionInfo.ReturnType; - var useThunk = false; //buildData.Platform.HasDynamicCodeExecutionSupport; // TODO: fix marshaing some types when using thunks on dotnet7 + var useThunk = buildData.Platform.HasDynamicCodeExecutionSupport; if (useThunk) { // Convert parameters into managed format as boxed values