Fix managed arrays interop bug when passed via generic object parameter
#2613
This commit is contained in:
@@ -15,8 +15,8 @@ namespace FlaxEngine.Interop
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedHandleMarshaller.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedOut, typeof(ManagedHandleMarshaller.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedHandleMarshaller.ManagedToNativeState))]
|
||||
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedOut, typeof(ManagedHandleMarshaller.ManagedToNativeState))]
|
||||
[CustomMarshaller(typeof(object), MarshalMode.ElementIn, typeof(ManagedHandleMarshaller.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(object), MarshalMode.ManagedToUnmanagedOut, typeof(ManagedHandleMarshaller.NativeToManaged))]
|
||||
[CustomMarshaller(typeof(object), MarshalMode.UnmanagedToManagedIn, typeof(ManagedHandleMarshaller.NativeToManaged))]
|
||||
@@ -31,7 +31,20 @@ namespace FlaxEngine.Interop
|
||||
#endif
|
||||
public static class NativeToManaged
|
||||
{
|
||||
public static object ConvertToManaged(IntPtr unmanaged) => unmanaged == IntPtr.Zero ? null : ManagedHandle.FromIntPtr(unmanaged).Target;
|
||||
public static object ConvertToManaged(IntPtr unmanaged)
|
||||
{
|
||||
if (unmanaged == IntPtr.Zero)
|
||||
return null;
|
||||
object managed = ManagedHandle.FromIntPtr(unmanaged).Target;
|
||||
if (managed is ManagedArray managedArray)
|
||||
{
|
||||
var managedArrayHandle = ManagedHandle.Alloc(managedArray, GCHandleType.Normal);
|
||||
managed = NativeInterop.MarshalToManaged((IntPtr)managedArrayHandle, managedArray.ArrayType);
|
||||
managedArrayHandle.Free();
|
||||
}
|
||||
return managed;
|
||||
}
|
||||
|
||||
public static IntPtr ConvertToUnmanaged(object managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero;
|
||||
|
||||
public static void Free(IntPtr unmanaged)
|
||||
@@ -40,6 +53,52 @@ namespace FlaxEngine.Interop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
public struct ManagedToNativeState
|
||||
{
|
||||
ManagedArray managedArray;
|
||||
IntPtr handle;
|
||||
|
||||
public void FromManaged(object managed)
|
||||
{
|
||||
if (managed == null)
|
||||
return;
|
||||
if (managed is Array arr)
|
||||
{
|
||||
var type = managed.GetType();
|
||||
var elementType = type.GetElementType();
|
||||
if (NativeInterop.ArrayFactory.GetMarshalledType(elementType) == elementType)
|
||||
{
|
||||
// Use pooled managed array wrapper to be passed around as handle to it
|
||||
(ManagedHandle tmp, managedArray) = ManagedArray.WrapPooledArray(arr);
|
||||
handle = ManagedHandle.ToIntPtr(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert array contents to be properly accessed by the native code (as GCHandles array)
|
||||
managedArray = NativeInterop.ManagedArrayToGCHandleWrappedArray(arr);
|
||||
handle = ManagedHandle.ToIntPtr(ManagedHandle.Alloc(managedArray));
|
||||
managedArray = null; // It's not pooled
|
||||
}
|
||||
}
|
||||
else
|
||||
handle = ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
|
||||
}
|
||||
|
||||
public IntPtr ToUnmanaged()
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void Free()
|
||||
{
|
||||
managedArray?.FreePooled();
|
||||
}
|
||||
}
|
||||
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
@@ -50,12 +109,6 @@ namespace FlaxEngine.Interop
|
||||
|
||||
public static void Free(IntPtr unmanaged)
|
||||
{
|
||||
// This is a weak handle, no need to free it
|
||||
/*
|
||||
if (unmanaged == IntPtr.Zero)
|
||||
return;
|
||||
ManagedHandle.FromIntPtr(unmanaged).Free();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +395,7 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
public static Dictionary<T, U> ConvertToManaged(IntPtr unmanaged) => DictionaryMarshaller<T, U>.ToManaged(unmanaged);
|
||||
public static IntPtr ConvertToUnmanaged(Dictionary<T, U> managed) => DictionaryMarshaller<T, U>.ToNative(managed, GCHandleType.Weak);
|
||||
|
||||
public static void Free(IntPtr unmanaged)
|
||||
{
|
||||
//DictionaryMarshaller<T, U>.Free(unmanaged); // No need to free weak handles
|
||||
@@ -614,6 +668,7 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
public static string ConvertToManaged(IntPtr unmanaged) => ManagedString.ToManaged(unmanaged);
|
||||
public static unsafe IntPtr ConvertToUnmanaged(string managed) => managed == null ? IntPtr.Zero : ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
|
||||
|
||||
public static void Free(IntPtr unmanaged)
|
||||
{
|
||||
//ManagedString.Free(unmanaged); // No need to free weak handles
|
||||
|
||||
@@ -1459,8 +1459,8 @@ namespace Flax.Build.Bindings
|
||||
public static class NativeToManaged
|
||||
{
|
||||
public static {{classInfo.Name}} ConvertToManaged(IntPtr unmanaged) => Unsafe.As<{{classInfo.Name}}>(ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged));
|
||||
public static IntPtr ConvertToUnmanaged({{classInfo.Name}} managed) => ManagedHandleMarshaller.ManagedToNative.ConvertToUnmanaged(managed);
|
||||
public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.NativeToManaged.Free(unmanaged);
|
||||
public static IntPtr ConvertToUnmanaged({{classInfo.Name}} managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero;
|
||||
public static void Free(IntPtr unmanaged) {}
|
||||
}
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
@@ -1468,8 +1468,8 @@ namespace Flax.Build.Bindings
|
||||
public static class ManagedToNative
|
||||
{
|
||||
public static {{classInfo.Name}} ConvertToManaged(IntPtr unmanaged) => Unsafe.As<{{classInfo.Name}}>(ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged));
|
||||
public static IntPtr ConvertToUnmanaged({{classInfo.Name}} managed) => ManagedHandleMarshaller.ManagedToNative.ConvertToUnmanaged(managed);
|
||||
public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.ManagedToNative.Free(unmanaged);
|
||||
public static IntPtr ConvertToUnmanaged({{classInfo.Name}} managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero;
|
||||
public static void Free(IntPtr unmanaged) {}
|
||||
}
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
|
||||
Reference in New Issue
Block a user