diff --git a/Source/Engine/Engine/NativeInterop.Managed.cs b/Source/Engine/Engine/NativeInterop.Managed.cs index e4dc449bc..f36798ece 100644 --- a/Source/Engine/Engine/NativeInterop.Managed.cs +++ b/Source/Engine/Engine/NativeInterop.Managed.cs @@ -371,7 +371,6 @@ namespace FlaxEngine.Interop { if (handle == IntPtr.Zero) return; - ManagedHandlePool.FreeHandle(handle); handle = IntPtr.Zero; } diff --git a/Source/Engine/Engine/NativeInterop.Marshallers.cs b/Source/Engine/Engine/NativeInterop.Marshallers.cs index 3ea8a5faa..74d6e6bad 100644 --- a/Source/Engine/Engine/NativeInterop.Marshallers.cs +++ b/Source/Engine/Engine/NativeInterop.Marshallers.cs @@ -183,6 +183,9 @@ namespace FlaxEngine.Interop public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.Free(unmanaged); } +#if FLAX_EDITOR + [HideInEditor] +#endif [CustomMarshaller(typeof(Array), MarshalMode.ManagedToUnmanagedIn, typeof(SystemArrayMarshaller.ManagedToNative))] [CustomMarshaller(typeof(Array), MarshalMode.UnmanagedToManagedOut, typeof(SystemArrayMarshaller.ManagedToNative))] [CustomMarshaller(typeof(Array), MarshalMode.ManagedToUnmanagedOut, typeof(SystemArrayMarshaller.NativeToManaged))] @@ -251,6 +254,74 @@ namespace FlaxEngine.Interop } } +#if FLAX_EDITOR + [HideInEditor] +#endif + [CustomMarshaller(typeof(object[]), MarshalMode.ManagedToUnmanagedIn, typeof(SystemObjectArrayMarshaller.ManagedToNative))] + [CustomMarshaller(typeof(object[]), MarshalMode.UnmanagedToManagedOut, typeof(SystemObjectArrayMarshaller.ManagedToNative))] + [CustomMarshaller(typeof(object[]), MarshalMode.ManagedToUnmanagedOut, typeof(SystemObjectArrayMarshaller.NativeToManaged))] + [CustomMarshaller(typeof(object[]), MarshalMode.UnmanagedToManagedIn, typeof(SystemObjectArrayMarshaller.NativeToManaged))] + public static unsafe class SystemObjectArrayMarshaller + { +#if FLAX_EDITOR + [HideInEditor] +#endif + public struct ManagedToNative + { + ManagedHandle handle; + + public void FromManaged(object[] managed) + { + if (managed != null) + { + var managedArray = NativeInterop.ManagedArrayToGCHandleWrappedArray(managed); + handle = ManagedHandle.Alloc(managedArray, GCHandleType.Weak); + } + } + + public IntPtr ToUnmanaged() + { + return ManagedHandle.ToIntPtr(handle); + } + + public void Free() + { + handle.Free(); + } + } + +#if FLAX_EDITOR + [HideInEditor] +#endif + public struct NativeToManaged + { + ManagedHandle handle; + + public void FromUnmanaged(IntPtr unmanaged) + { + if (unmanaged == IntPtr.Zero) + return; + handle = ManagedHandle.FromIntPtr(unmanaged); + } + + public object[] ToManaged() + { + object[] result = null; + if (handle.IsAllocated) + { + var managedArray = Unsafe.As(handle.Target); + result = NativeInterop.GCHandleArrayToManagedArray(managedArray); + } + return result; + } + + public void Free() + { + handle.Free(); + } + } + } + #if FLAX_EDITOR [HideInEditor] #endif diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index f399dd67c..b825f5ac1 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -521,7 +521,7 @@ namespace Flax.Build.Bindings returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.SystemTypeMarshaller))"; else if (returnValueType == "CultureInfo") returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.CultureInfoMarshaller))"; - else if (functionInfo.ReturnType.Type == "Variant") + else if (functionInfo.ReturnType.Type == "Variant") // object returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.ManagedHandleMarshaller))"; else if (FindApiTypeInfo(buildData, functionInfo.ReturnType, caller)?.IsInterface ?? false) { @@ -530,6 +530,8 @@ namespace Flax.Build.Bindings } else if (functionInfo.ReturnType.Type == "MonoArray" || functionInfo.ReturnType.Type == "MArray") returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.SystemArrayMarshaller))"; + else if (returnValueType == "object[]") + returnMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.SystemObjectArrayMarshaller))"; else if (functionInfo.ReturnType.Type == "Array" || functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "DataContainer" || functionInfo.ReturnType.Type == "BytesContainer" || returnNativeType == "Array") returnMarshalType = $"MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = nameof(__returnCount))"; else if (functionInfo.ReturnType.Type == "Dictionary") @@ -579,6 +581,8 @@ namespace Flax.Build.Bindings parameterMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.ManagedHandleMarshaller))"; else if (parameterInfo.Type.Type == "MonoArray" || parameterInfo.Type.Type == "MArray") parameterMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.SystemArrayMarshaller))"; + else if (nativeType == "object[]") + parameterMarshalType = "MarshalUsing(typeof(FlaxEngine.Interop.SystemObjectArrayMarshaller))"; else if (parameterInfo.Type.Type == "Array" && parameterInfo.Type.GenericArgs.Count > 0 && parameterInfo.Type.GenericArgs[0].Type == "bool") parameterMarshalType = $"MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = {(!functionInfo.IsStatic ? 1 : 0) + functionInfo.Parameters.Count + (functionInfo.Glue.CustomParameters.FindIndex(x => x.Name == $"__{parameterInfo.Name}Count"))})"; else if (parameterInfo.Type.Type == "Array" || parameterInfo.Type.Type == "Span" || parameterInfo.Type.Type == "DataContainer" || parameterInfo.Type.Type == "BytesContainer" || nativeType == "Array")