Fix using managed arrays with Variant in dotnet7

This commit is contained in:
Wojtek Figat
2023-03-27 19:41:53 +02:00
parent 8d7225c056
commit ed13de2d5b
7 changed files with 121 additions and 84 deletions

View File

@@ -391,8 +391,8 @@ namespace FlaxEditor.Content.Import
MaxSize = managed.MaxSize, MaxSize = managed.MaxSize,
TextureGroup = managed.TextureGroup, TextureGroup = managed.TextureGroup,
Size = managed.Size, Size = managed.Size,
SpriteAreas = managed.SpriteAreas?.Length > 0 ? ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(NativeInterop.ManagedArrayToGCHandleArray(managed.SpriteAreas))) : IntPtr.Zero, SpriteAreas = managed.SpriteAreas?.Length > 0 ? ManagedHandle.ToIntPtr(NativeInterop.ManagedArrayToGCHandleWrappedArray(managed.SpriteAreas)) : IntPtr.Zero,
SpriteNames = managed.SpriteNames?.Length > 0 ? ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(NativeInterop.ManagedArrayToGCHandleArray(managed.SpriteNames))) : IntPtr.Zero, SpriteNames = managed.SpriteNames?.Length > 0 ? ManagedHandle.ToIntPtr(NativeInterop.ManagedArrayToGCHandleWrappedArray(managed.SpriteNames)) : IntPtr.Zero,
}; };
} }
internal static void Free(InternalOptionsNative unmanaged) internal static void Free(InternalOptionsNative unmanaged)

View File

@@ -157,39 +157,49 @@ namespace FlaxEngine
/// </summary> /// </summary>
public unsafe class ManagedArray public unsafe class ManagedArray
{ {
private ManagedHandle pinnedArrayHandle; private ManagedHandle _pinnedArrayHandle;
private IntPtr unmanagedData; private IntPtr _unmanagedData;
private Type elementType; private Type _arrayType;
private int elementSize; private Type _elementType;
private int length; private int _elementSize;
private int _length;
public static ManagedArray WrapNewArray(Array arr) => new ManagedArray(arr); public static ManagedArray WrapNewArray(Array arr) => new ManagedArray(arr, arr.GetType());
public static ManagedArray WrapNewArray(Array arr, Type arrayType) => new ManagedArray(arr, arrayType);
/// <summary> /// <summary>
/// Returns an instance of ManagedArray from shared pool. /// Returns an instance of ManagedArray from shared pool.
/// </summary> /// </summary>
/// <remarks> /// <remarks>The resources must be released by calling FreePooled() instead of Free()-method.</remarks>
/// The resources must be released by calling FreePooled() instead of Free()-method.
/// </remarks>
public static ManagedArray WrapPooledArray(Array arr) public static ManagedArray WrapPooledArray(Array arr)
{ {
ManagedArray managedArray = ManagedArrayPool.Get(); ManagedArray managedArray = ManagedArrayPool.Get();
managedArray.WrapArray(arr); managedArray.WrapArray(arr, arr.GetType());
return managedArray; return managedArray;
} }
internal static ManagedArray AllocateNewArray(int length, Type elementType)
=> new ManagedArray((IntPtr)NativeInterop.NativeAlloc(length, Marshal.SizeOf(elementType)), length, elementType);
internal static ManagedArray AllocateNewArray(IntPtr ptr, int length, Type elementType)
=> new ManagedArray(ptr, length, elementType);
/// <summary> /// <summary>
/// Returns an instance of ManagedArray from shared pool. /// Returns an instance of ManagedArray from shared pool.
/// </summary> /// </summary>
/// <remarks> /// <remarks>The resources must be released by calling FreePooled() instead of Free()-method.</remarks>
/// The resources must be released by calling FreePooled() instead of Free()-method. public static ManagedArray WrapPooledArray(Array arr, Type arrayType)
/// </remarks> {
ManagedArray managedArray = ManagedArrayPool.Get();
managedArray.WrapArray(arr, arrayType);
return managedArray;
}
internal static ManagedArray AllocateNewArray(int length, Type arrayType, Type elementType)
=> new ManagedArray((IntPtr)NativeInterop.NativeAlloc(length, Marshal.SizeOf(elementType)), length, arrayType, elementType);
internal static ManagedArray AllocateNewArray(IntPtr ptr, int length, Type arrayType, Type elementType)
=> new ManagedArray(ptr, length, arrayType, elementType);
/// <summary>
/// Returns an instance of ManagedArray from shared pool.
/// </summary>
/// <remarks>The resources must be released by calling FreePooled() instead of Free()-method.</remarks>
public static ManagedArray AllocatePooledArray<T>(T* ptr, int length) where T : unmanaged public static ManagedArray AllocatePooledArray<T>(T* ptr, int length) where T : unmanaged
{ {
ManagedArray managedArray = ManagedArrayPool.Get(); ManagedArray managedArray = ManagedArrayPool.Get();
@@ -200,67 +210,67 @@ namespace FlaxEngine
/// <summary> /// <summary>
/// Returns an instance of ManagedArray from shared pool. /// Returns an instance of ManagedArray from shared pool.
/// </summary> /// </summary>
/// <remarks> /// <remarks>The resources must be released by calling FreePooled() instead of Free()-method.</remarks>
/// The resources must be released by calling FreePooled() instead of Free()-method.
/// </remarks>
public static ManagedArray AllocatePooledArray<T>(int length) where T : unmanaged public static ManagedArray AllocatePooledArray<T>(int length) where T : unmanaged
{ {
ManagedArray managedArray = ManagedArrayPool.Get(); ManagedArray managedArray = ManagedArrayPool.Get();
managedArray.Allocate((IntPtr)NativeInterop.NativeAlloc(length, Unsafe.SizeOf<T>()), length, typeof(T)); managedArray.Allocate((T*)NativeInterop.NativeAlloc(length, Unsafe.SizeOf<T>()), length);
return managedArray; return managedArray;
} }
public ManagedArray(Array arr) => WrapArray(arr); public ManagedArray(Array arr, Type elementType) => WrapArray(arr, elementType);
internal void WrapArray(Array arr) internal void WrapArray(Array arr, Type arrayType)
{ {
pinnedArrayHandle = ManagedHandle.Alloc(arr, GCHandleType.Pinned); _pinnedArrayHandle = ManagedHandle.Alloc(arr, GCHandleType.Pinned);
unmanagedData = Marshal.UnsafeAddrOfPinnedArrayElement(arr, 0); _unmanagedData = Marshal.UnsafeAddrOfPinnedArrayElement(arr, 0);
length = arr.Length; _length = arr.Length;
elementType = arr.GetType().GetElementType(); _arrayType = arrayType;
elementSize = Marshal.SizeOf(elementType); _elementType = arr.GetType().GetElementType();
_elementSize = Marshal.SizeOf(_elementType);
} }
internal void Allocate<T>(T* ptr, int length) where T : unmanaged internal void Allocate<T>(T* ptr, int length) where T : unmanaged
{ {
unmanagedData = new IntPtr(ptr); _unmanagedData = new IntPtr(ptr);
this.length = length; _length = length;
elementType = typeof(T); _arrayType = typeof(T).MakeArrayType();
elementSize = Unsafe.SizeOf<T>(); _elementType = typeof(T);
} _elementSize = Unsafe.SizeOf<T>();
internal void Allocate(IntPtr ptr, int length, Type elementType)
{
unmanagedData = ptr;
this.length = length;
this.elementType = elementType;
elementSize = Marshal.SizeOf(elementType);
} }
private ManagedArray() private ManagedArray()
{ {
} }
private ManagedArray(IntPtr ptr, int length, Type elementType) => Allocate(ptr, length, elementType); private ManagedArray(IntPtr ptr, int length, Type arrayType, Type elementType)
{
Assert.IsTrue(arrayType.IsArray);
_unmanagedData = ptr;
_length = length;
_arrayType = arrayType;
_elementType = elementType;
_elementSize = Marshal.SizeOf(elementType);
}
~ManagedArray() ~ManagedArray()
{ {
if (unmanagedData != IntPtr.Zero) if (_unmanagedData != IntPtr.Zero)
Free(); Free();
} }
public void Free() public void Free()
{ {
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
if (pinnedArrayHandle.IsAllocated) if (_pinnedArrayHandle.IsAllocated)
{ {
pinnedArrayHandle.Free(); _pinnedArrayHandle.Free();
unmanagedData = IntPtr.Zero; _unmanagedData = IntPtr.Zero;
} }
if (unmanagedData != IntPtr.Zero) if (_unmanagedData != IntPtr.Zero)
{ {
NativeInterop.NativeFree(unmanagedData.ToPointer()); NativeInterop.NativeFree(_unmanagedData.ToPointer());
unmanagedData = IntPtr.Zero; _unmanagedData = IntPtr.Zero;
} }
} }
@@ -270,17 +280,21 @@ namespace FlaxEngine
ManagedArrayPool.Put(this); ManagedArrayPool.Put(this);
} }
internal IntPtr Pointer => unmanagedData; internal IntPtr Pointer => _unmanagedData;
internal int Length => length; internal int Length => _length;
internal int ElementSize => elementSize; internal int ElementSize => _elementSize;
public Span<T> ToSpan<T>() where T : struct => new Span<T>(unmanagedData.ToPointer(), length); internal Type ElementType => _elementType;
public T[] ToArray<T>() where T : struct => new Span<T>(unmanagedData.ToPointer(), length).ToArray(); internal Type ArrayType => _arrayType;
public Array ToArray() => ArrayCast.ToArray(new Span<byte>(unmanagedData.ToPointer(), length * elementSize), elementType); public Span<T> ToSpan<T>() where T : struct => new Span<T>(_unmanagedData.ToPointer(), _length);
public T[] ToArray<T>() where T : struct => new Span<T>(_unmanagedData.ToPointer(), _length).ToArray();
public Array ToArray() => ArrayCast.ToArray(new Span<byte>(_unmanagedData.ToPointer(), _length * _elementSize), _elementType);
/// <summary> /// <summary>
/// Creates an Array of the specified type from span of bytes. /// Creates an Array of the specified type from span of bytes.
@@ -1251,6 +1265,8 @@ namespace FlaxEngine
internal static IntPtr[] ManagedArrayToGCHandleArray(Array array) internal static IntPtr[] ManagedArrayToGCHandleArray(Array array)
{ {
if (array.Length == 0)
return Array.Empty<IntPtr>();
IntPtr[] pointerArray = new IntPtr[array.Length]; IntPtr[] pointerArray = new IntPtr[array.Length];
for (int i = 0; i < pointerArray.Length; i++) for (int i = 0; i < pointerArray.Length; i++)
{ {
@@ -1261,6 +1277,12 @@ namespace FlaxEngine
return pointerArray; return pointerArray;
} }
internal static ManagedArray ManagedArrayToGCHandleWrappedArray(Array array)
{
IntPtr[] pointerArray = ManagedArrayToGCHandleArray(array);
return ManagedArray.WrapNewArray(pointerArray, array.GetType());
}
internal static T[] NativeArrayToManagedArray<T, U>(Span<U> nativeSpan, Func<U, T> toManagedFunc) internal static T[] NativeArrayToManagedArray<T, U>(Span<U> nativeSpan, Func<U, T> toManagedFunc)
{ {
T[] managedArray = new T[nativeSpan.Length]; T[] managedArray = new T[nativeSpan.Length];
@@ -1877,11 +1899,11 @@ namespace FlaxEngine
var marshalledType = ArrayFactory.GetMarshalledType(elementType); var marshalledType = ArrayFactory.GetMarshalledType(elementType);
ManagedArray managedArray; ManagedArray managedArray;
if (marshalledType == elementType) if (marshalledType == elementType)
managedArray = ManagedArray.WrapNewArray(arr); managedArray = ManagedArray.WrapNewArray(arr, type);
else if (elementType.IsValueType) else if (elementType.IsValueType)
{ {
// Convert array of custom structures into internal native layout // Convert array of custom structures into internal native layout
managedArray = ManagedArray.AllocateNewArray(arr.Length, marshalledType); managedArray = ManagedArray.AllocateNewArray(arr.Length, type, marshalledType);
IntPtr managedArrayPtr = managedArray.Pointer; IntPtr managedArrayPtr = managedArray.Pointer;
for (int i = 0; i < arr.Length; i++) for (int i = 0; i < arr.Length; i++)
{ {
@@ -1890,7 +1912,7 @@ namespace FlaxEngine
} }
} }
else else
managedArray = ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(arr)); managedArray = ManagedArrayToGCHandleWrappedArray(arr);
managedPtr = ManagedHandle.ToIntPtr(managedArray, GCHandleType.Weak); managedPtr = ManagedHandle.ToIntPtr(managedArray, GCHandleType.Weak);
} }
} }
@@ -2325,21 +2347,30 @@ namespace FlaxEngine
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
internal static ManagedHandle NewArray(ManagedHandle typeHandle, long size) internal static ManagedHandle NewArray(ManagedHandle typeHandle, long size)
{ {
Type type = Unsafe.As<Type>(typeHandle.Target); Type elementType = Unsafe.As<Type>(typeHandle.Target);
Type marshalledType = ArrayFactory.GetMarshalledType(type); Type marshalledType = ArrayFactory.GetMarshalledType(elementType);
Type arrayType = elementType.MakeArrayType();
if (marshalledType.IsValueType) if (marshalledType.IsValueType)
{ {
ManagedArray managedArray = ManagedArray.AllocateNewArray((int)size, marshalledType); ManagedArray managedArray = ManagedArray.AllocateNewArray((int)size, arrayType, marshalledType);
return ManagedHandle.Alloc(managedArray); return ManagedHandle.Alloc(managedArray);
} }
else else
{ {
Array arr = ArrayFactory.CreateArray(type, size); Array arr = ArrayFactory.CreateArray(elementType, size);
ManagedArray managedArray = ManagedArray.WrapNewArray(arr); ManagedArray managedArray = ManagedArray.WrapNewArray(arr, arrayType);
return ManagedHandle.Alloc(managedArray); return ManagedHandle.Alloc(managedArray);
} }
} }
[UnmanagedCallersOnly]
internal static unsafe ManagedHandle GetArrayTypeFromElementType(ManagedHandle elementTypeHandle)
{
Type elementType = Unsafe.As<Type>(elementTypeHandle.Target);
Type classType = elementType.MakeArrayType();
return GetTypeGCHandle(classType);
}
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
internal static unsafe IntPtr GetArrayPointer(ManagedHandle arrayHandle) internal static unsafe IntPtr GetArrayPointer(ManagedHandle arrayHandle)
{ {
@@ -2392,8 +2423,10 @@ namespace FlaxEngine
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
internal static ManagedHandle GetObjectType(ManagedHandle handle) internal static ManagedHandle GetObjectType(ManagedHandle handle)
{ {
var obj = handle.Target; object obj = handle.Target;
Type classType = obj.GetType(); Type classType = obj.GetType();
if (classType == typeof(ManagedArray))
classType = ((ManagedArray)obj).ArrayType;
return GetTypeGCHandle(classType); return GetTypeGCHandle(classType);
} }
@@ -2688,15 +2721,17 @@ namespace FlaxEngine
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
internal static unsafe int NativeSizeOf(ManagedHandle typeHandle, uint* align) internal static unsafe int NativeSizeOf(ManagedHandle typeHandle)
{ {
Type type = Unsafe.As<Type>(typeHandle.Target); Type type = Unsafe.As<Type>(typeHandle.Target);
Type nativeType = GetInternalType(type) ?? type; Type nativeType = GetInternalType(type) ?? type;
if (nativeType == typeof(Version)) if (nativeType == typeof(Version))
nativeType = typeof(VersionNative); nativeType = typeof(VersionNative);
int size;
int size = Marshal.SizeOf(nativeType); if (nativeType.IsClass)
*align = (uint)size; // Is this correct? size = sizeof(IntPtr);
else
size = Marshal.SizeOf(nativeType);
return size; return size;
} }
@@ -2927,6 +2962,7 @@ namespace FlaxEngine
break; break;
} }
case Type _ when type.IsArray: case Type _ when type.IsArray:
case Type _ when type == typeof(ManagedArray):
monoType = MTypes.Array; monoType = MTypes.Array;
break; break;
case Type _ when type.IsValueType && !type.IsEnum && !type.IsPrimitive: case Type _ when type.IsValueType && !type.IsEnum && !type.IsPrimitive:

View File

@@ -88,7 +88,7 @@ namespace FlaxEngine
var elementType = typeof(TRet).GetElementType(); var elementType = typeof(TRet).GetElementType();
if (ArrayFactory.GetMarshalledType(elementType) == elementType) if (ArrayFactory.GetMarshalledType(elementType) == elementType)
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnValue)), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnValue)), GCHandleType.Weak);
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As<Array>(returnValue))), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArrayToGCHandleWrappedArray(Unsafe.As<Array>(returnValue)), GCHandleType.Weak);
} }
return ManagedHandle.ToIntPtr(returnValue, GCHandleType.Weak); return ManagedHandle.ToIntPtr(returnValue, GCHandleType.Weak);
} }
@@ -108,7 +108,7 @@ namespace FlaxEngine
if (returnType.IsArray && ArrayFactory.GetMarshalledType(returnType.GetElementType()) == returnType.GetElementType()) if (returnType.IsArray && ArrayFactory.GetMarshalledType(returnType.GetElementType()) == returnType.GetElementType())
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnObject)), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnObject)), GCHandleType.Weak);
if (returnType.IsArray) if (returnType.IsArray)
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As<Array>(returnObject))), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArrayToGCHandleWrappedArray(Unsafe.As<Array>(returnObject)), GCHandleType.Weak);
return ManagedHandle.ToIntPtr(returnObject, GCHandleType.Weak); return ManagedHandle.ToIntPtr(returnObject, GCHandleType.Weak);
} }
@@ -129,7 +129,7 @@ namespace FlaxEngine
var elementType = typeof(TRet).GetElementType(); var elementType = typeof(TRet).GetElementType();
if (ArrayFactory.GetMarshalledType(elementType) == elementType) if (ArrayFactory.GetMarshalledType(elementType) == elementType)
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnValue)), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnValue)), GCHandleType.Weak);
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As<Array>(returnValue))), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArrayToGCHandleWrappedArray(Unsafe.As<Array>(returnValue)), GCHandleType.Weak);
} }
// Match Mono bindings and pass value as pointer to prevent boxing it // Match Mono bindings and pass value as pointer to prevent boxing it
if (typeof(TRet) == typeof(System.Boolean)) if (typeof(TRet) == typeof(System.Boolean))
@@ -166,7 +166,7 @@ namespace FlaxEngine
var elementType = returnType.GetElementType(); var elementType = returnType.GetElementType();
if (ArrayFactory.GetMarshalledType(elementType) == elementType) if (ArrayFactory.GetMarshalledType(elementType) == elementType)
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnObject)), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(Unsafe.As<Array>(returnObject)), GCHandleType.Weak);
return ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As<Array>(returnObject))), GCHandleType.Weak); return ManagedHandle.ToIntPtr(ManagedArrayToGCHandleWrappedArray(Unsafe.As<Array>(returnObject)), GCHandleType.Weak);
} }
// Match Mono bindings and pass value as pointer to prevent boxing it // Match Mono bindings and pass value as pointer to prevent boxing it
if (returnType == typeof(System.Boolean)) if (returnType == typeof(System.Boolean))

View File

@@ -1200,9 +1200,10 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp
{ {
// Box instance into C# object // Box instance into C# object
MObject* instanceObject = MUtils::BoxVariant(instance); MObject* instanceObject = MUtils::BoxVariant(instance);
const MClass* instanceObjectClass = MCore::Object::GetClass(instanceObject);
// Validate instance // Validate instance
if (!instanceObject || !MCore::Object::GetClass(instanceObject)->IsSubClassOf(mMethod->GetParentClass(), withInterfaces)) if (!instanceObject || !instanceObjectClass->IsSubClassOf(mMethod->GetParentClass(), withInterfaces))
{ {
if (!instanceObject) if (!instanceObject)
LOG(Error, "Failed to call method '{0}.{1}' (args count: {2}) without object instance", String(mMethod->GetParentClass()->GetFullName()), String(mMethod->GetName()), parametersCount); LOG(Error, "Failed to call method '{0}.{1}' (args count: {2}) without object instance", String(mMethod->GetParentClass()->GetFullName()), String(mMethod->GetName()), parametersCount);
@@ -1212,7 +1213,7 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp
} }
// For value-types instance is the actual boxed object data, not te object itself // For value-types instance is the actual boxed object data, not te object itself
mInstance = MCore::Object::GetClass(instanceObject)->IsValueType() ? MCore::Object::Unbox(instanceObject) : instanceObject; mInstance = instanceObjectClass->IsValueType() ? MCore::Object::Unbox(instanceObject) : instanceObject;
} }
// Marshal parameters // Marshal parameters

View File

@@ -389,7 +389,8 @@ Variant MUtils::UnboxVariant(MObject* value)
case MTypes::Array: case MTypes::Array:
{ {
void* ptr = MCore::Array::GetAddress((MArray*)value); void* ptr = MCore::Array::GetAddress((MArray*)value);
if (klass->GetElementClass() == MCore::TypeCache::Byte) MClass* elementClass = klass->GetElementClass();
if (elementClass == MCore::TypeCache::Byte)
{ {
Variant v; Variant v;
v.SetBlob(ptr, MCore::Array::GetLength((MArray*)value)); v.SetBlob(ptr, MCore::Array::GetLength((MArray*)value));
@@ -401,7 +402,6 @@ Variant MUtils::UnboxVariant(MObject* value)
auto& array = v.AsArray(); auto& array = v.AsArray();
array.Resize(MCore::Array::GetLength((MArray*)value)); array.Resize(MCore::Array::GetLength((MArray*)value));
const StringAnsiView elementTypename(*fullname, fullname.Length() - 2); const StringAnsiView elementTypename(*fullname, fullname.Length() - 2);
MClass* elementClass = klass->GetElementClass();
const int32 elementSize = elementClass->GetInstanceSize(); const int32 elementSize = elementClass->GetInstanceSize();
if (elementClass->IsEnum()) if (elementClass->IsEnum())
{ {

View File

@@ -374,8 +374,9 @@ MArray* MCore::Array::New(const MClass* elementKlass, int32 length)
MClass* MCore::Array::GetClass(MClass* elementKlass) MClass* MCore::Array::GetClass(MClass* elementKlass)
{ {
MISSING_CODE("TODO: MCore::Array::GetClass"); // TODO: MCore::Object::GetClass static void* GetArrayLengthPtr = GetStaticMethodPointer(TEXT("GetArrayTypeFromElementType"));
return nullptr; void* classHandle = CallStaticMethod<void*, void*>(GetArrayLengthPtr, elementKlass->_handle);
return GetOrCreateClass((void*)classHandle);
} }
int32 MCore::Array::GetLength(const MArray* obj) int32 MCore::Array::GetLength(const MArray* obj)
@@ -806,9 +807,8 @@ uint32 MClass::GetInstanceSize() const
{ {
if (_size != 0) if (_size != 0)
return _size; return _size;
uint32 align;
static void* NativeSizeOfPtr = GetStaticMethodPointer(TEXT("NativeSizeOf")); static void* NativeSizeOfPtr = GetStaticMethodPointer(TEXT("NativeSizeOf"));
_size = CallStaticMethod<int, void*, uint32*>(NativeSizeOfPtr, _handle, &align); _size = CallStaticMethod<int, void*>(NativeSizeOfPtr, _handle);
return _size; return _size;
} }

View File

@@ -1541,7 +1541,7 @@ namespace Flax.Build.Bindings
{ {
// Array elements passed as GCHandles // Array elements passed as GCHandles
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<{originalElementType}>((ManagedArray)ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null"); toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<{originalElementType}>((ManagedArray)ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null");
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(NativeInterop.ManagedArrayToGCHandleArray(managed.{fieldInfo.Name})), GCHandleType.Weak) : IntPtr.Zero"); toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(NativeInterop.ManagedArrayToGCHandleWrappedArray(managed.{fieldInfo.Name}), GCHandleType.Weak) : IntPtr.Zero");
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).ToSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}"); freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).ToSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).ToSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}"); freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).ToSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
} }