Improve array allocations when marshalling method parameters
This commit is contained in:
@@ -391,8 +391,8 @@ namespace FlaxEditor.Content.Import
|
||||
MaxSize = managed.MaxSize,
|
||||
TextureGroup = managed.TextureGroup,
|
||||
Size = managed.Size,
|
||||
SpriteAreas = managed.SpriteAreas?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(NativeInterop.ManagedArrayToGCHandleArray(managed.SpriteAreas)))) : IntPtr.Zero,
|
||||
SpriteNames = managed.SpriteNames?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(NativeInterop.ManagedArrayToGCHandleArray(managed.SpriteNames)))) : IntPtr.Zero,
|
||||
SpriteAreas = managed.SpriteAreas?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(NativeInterop.ManagedArrayToGCHandleArray(managed.SpriteAreas)))) : IntPtr.Zero,
|
||||
SpriteNames = managed.SpriteNames?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(NativeInterop.ManagedArrayToGCHandleArray(managed.SpriteNames)))) : IntPtr.Zero,
|
||||
};
|
||||
}
|
||||
internal static void Free(InternalOptionsNative unmanaged)
|
||||
|
||||
@@ -200,40 +200,85 @@ namespace FlaxEngine
|
||||
/// </summary>
|
||||
internal unsafe class ManagedArray
|
||||
{
|
||||
private Array array;
|
||||
private GCHandle pinnedArrayHandle;
|
||||
private IntPtr unmanagedData;
|
||||
private int elementSize;
|
||||
private int length;
|
||||
|
||||
internal ManagedArray(Array arr)
|
||||
internal static ManagedArray WrapNewArray(Array arr) => new ManagedArray(arr);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of ManagedArray from shared pool.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The resources must be released by calling FreePooled() instead of Free()-method.
|
||||
/// </remarks>
|
||||
internal static ManagedArray WrapPooledArray(Array arr)
|
||||
{
|
||||
array = arr;
|
||||
unmanagedData = IntPtr.Zero;
|
||||
ManagedArray managedArray = ManagedArrayPool.Get();
|
||||
managedArray.WrapArray(arr);
|
||||
return managedArray;
|
||||
}
|
||||
|
||||
internal static ManagedArray AllocateNewArray<T>(T* ptr, int length) where T : unmanaged => new ManagedArray(ptr, length, Unsafe.SizeOf<T>());
|
||||
|
||||
internal static ManagedArray AllocateNewArray(IntPtr ptr, int length, int elementSize) => new ManagedArray(ptr.ToPointer(), length, elementSize);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of ManagedArray from shared pool.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The resources must be released by calling FreePooled() instead of Free()-method.
|
||||
/// </remarks>
|
||||
internal static ManagedArray AllocatePooledArray<T>(T* ptr, int length) where T : unmanaged
|
||||
{
|
||||
ManagedArray managedArray = ManagedArrayPool.Get();
|
||||
managedArray.Allocate(ptr, length);
|
||||
return managedArray;
|
||||
}
|
||||
|
||||
internal ManagedArray(Array arr) => WrapArray(arr);
|
||||
|
||||
internal void WrapArray(Array arr)
|
||||
{
|
||||
pinnedArrayHandle = GCHandle.Alloc(arr, GCHandleType.Pinned);
|
||||
unmanagedData = Marshal.UnsafeAddrOfPinnedArrayElement(arr, 0);
|
||||
length = arr.Length;
|
||||
elementSize = Marshal.SizeOf(arr.GetType().GetElementType());
|
||||
}
|
||||
|
||||
private ManagedArray(void* ptr, int length, int elementSize)
|
||||
internal void Allocate<T>(T* ptr, int length) where T : unmanaged
|
||||
{
|
||||
array = null;
|
||||
this.unmanagedData = new IntPtr(ptr);
|
||||
unmanagedData = new IntPtr(ptr);
|
||||
this.length = length;
|
||||
elementSize = Unsafe.SizeOf<T>();
|
||||
}
|
||||
|
||||
internal void Allocate(IntPtr ptr, int length, int elementSize)
|
||||
{
|
||||
unmanagedData = ptr;
|
||||
this.length = length;
|
||||
this.elementSize = elementSize;
|
||||
}
|
||||
|
||||
private ManagedArray() { }
|
||||
|
||||
private ManagedArray(void* ptr, int length, int elementSize) => Allocate(new IntPtr(ptr), length, elementSize);
|
||||
|
||||
~ManagedArray()
|
||||
{
|
||||
if (unmanagedData != IntPtr.Zero || array != null)
|
||||
Release();
|
||||
if (unmanagedData != IntPtr.Zero)
|
||||
Free();
|
||||
}
|
||||
|
||||
internal void Release()
|
||||
internal void Free()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
if (pinnedArrayHandle.IsAllocated)
|
||||
{
|
||||
pinnedArrayHandle.Free();
|
||||
array = null;
|
||||
unmanagedData = IntPtr.Zero;
|
||||
}
|
||||
if (unmanagedData != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(unmanagedData);
|
||||
@@ -241,41 +286,63 @@ namespace FlaxEngine
|
||||
}
|
||||
}
|
||||
|
||||
internal IntPtr PointerToPinnedArray
|
||||
internal void FreePooled()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (array != null)
|
||||
{
|
||||
// Pin the array when it's accessed for the first time
|
||||
if (!pinnedArrayHandle.IsAllocated)
|
||||
pinnedArrayHandle = GCHandle.Alloc(array);
|
||||
return Marshal.UnsafeAddrOfPinnedArrayElement(array, 0);
|
||||
}
|
||||
else
|
||||
return unmanagedData;
|
||||
}
|
||||
Free();
|
||||
ManagedArrayPool.Put(this);
|
||||
}
|
||||
|
||||
internal void SetValue(IntPtr value, int index)
|
||||
{
|
||||
if (array != null)
|
||||
array.SetValue(value, index);
|
||||
else
|
||||
GetSpan<IntPtr>()[index] = value;
|
||||
}
|
||||
internal IntPtr GetPointer => unmanagedData;
|
||||
|
||||
internal int Length => length;
|
||||
|
||||
internal int ElementSize => elementSize;
|
||||
|
||||
internal Span<T> GetSpan<T>() where T : struct => array != null ? new Span<T>((T[]) array) : new Span<T>(unmanagedData.ToPointer(), length);
|
||||
internal Span<T> GetSpan<T>() where T : struct => new Span<T>(unmanagedData.ToPointer(), length);
|
||||
|
||||
internal T[] GetArray<T>() where T : struct => array != null ? (T[])array : new Span<T>(unmanagedData.ToPointer(), length).ToArray();
|
||||
internal T[] GetArray<T>() where T : struct => new Span<T>(unmanagedData.ToPointer(), length).ToArray();
|
||||
|
||||
internal static ManagedArray Get(Array arr) => new ManagedArray(arr);
|
||||
/// <summary>
|
||||
/// Provides a pool of pre-allocated ManagedArray that can be re-used.
|
||||
/// </summary>
|
||||
private static class ManagedArrayPool
|
||||
{
|
||||
private static List<ValueTuple<bool, ManagedArray>> pool = new List<ValueTuple<bool, ManagedArray>>();
|
||||
|
||||
internal static ManagedArray Get<T>(T* ptr, int length) where T : unmanaged => new ManagedArray(ptr, length, Unsafe.SizeOf<T>());
|
||||
internal static ManagedArray Get()
|
||||
{
|
||||
for (int i = 0; i < pool.Count; i++)
|
||||
{
|
||||
if (!pool[i].Item1)
|
||||
{
|
||||
var tuple = pool[i];
|
||||
tuple.Item1 = true;
|
||||
pool[i] = tuple;
|
||||
return tuple.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
var newTuple = (true, new ManagedArray());
|
||||
pool.Add(newTuple);
|
||||
return newTuple.Item2;
|
||||
}
|
||||
|
||||
internal static void Put(ManagedArray obj)
|
||||
{
|
||||
for (int i = 0; i < pool.Count; i++)
|
||||
{
|
||||
if (pool[i].Item2 == obj)
|
||||
{
|
||||
var tuple = pool[i];
|
||||
tuple.Item1 = false;
|
||||
pool[i] = tuple;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Tried to free non-pooled ManagedArray as pooled ManagedArray");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ManagedString
|
||||
@@ -446,7 +513,7 @@ namespace FlaxEngine
|
||||
public void FromManaged(Array managed)
|
||||
{
|
||||
if (managed != null)
|
||||
managedArray = ManagedArray.Get(managed);
|
||||
managedArray = ManagedArray.WrapPooledArray(managed);
|
||||
}
|
||||
|
||||
public IntPtr ToUnmanaged()
|
||||
@@ -462,8 +529,8 @@ namespace FlaxEngine
|
||||
{
|
||||
if (managedArray != null)
|
||||
{
|
||||
managedArray.FreePooled();
|
||||
handle.Free();
|
||||
managedArray.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,7 +634,7 @@ namespace FlaxEngine
|
||||
return;
|
||||
|
||||
GCHandle handle = GCHandle.FromIntPtr(new IntPtr(unmanaged));
|
||||
(Unsafe.As<ManagedArray>(handle.Target)).Release();
|
||||
(Unsafe.As<ManagedArray>(handle.Target)).Free();
|
||||
handle.Free();
|
||||
}
|
||||
|
||||
@@ -593,7 +660,7 @@ namespace FlaxEngine
|
||||
|
||||
numElements = managed.Length;
|
||||
|
||||
ManagedArray managedArray = ManagedArray.Get((TUnmanagedElement*)Marshal.AllocHGlobal(sizeof(TUnmanagedElement) * managed.Length), managed.Length);
|
||||
ManagedArray managedArray = ManagedArray.AllocatePooledArray((TUnmanagedElement*)Marshal.AllocHGlobal(sizeof(TUnmanagedElement) * managed.Length), managed.Length);
|
||||
var ptr = GCHandle.ToIntPtr(GCHandle.Alloc(managedArray));
|
||||
|
||||
return (TUnmanagedElement*)ptr;
|
||||
@@ -616,7 +683,7 @@ namespace FlaxEngine
|
||||
return;
|
||||
|
||||
GCHandle handle = GCHandle.FromIntPtr(new IntPtr(unmanaged));
|
||||
(Unsafe.As<ManagedArray>(handle.Target)).Release();
|
||||
(Unsafe.As<ManagedArray>(handle.Target)).FreePooled();
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
@@ -633,7 +700,8 @@ namespace FlaxEngine
|
||||
return;
|
||||
|
||||
managedArray = managed;
|
||||
unmanagedArray = ManagedArray.Get((TUnmanagedElement*)Marshal.AllocHGlobal(sizeof(TUnmanagedElement) * managed.Length), managed.Length);
|
||||
|
||||
unmanagedArray = ManagedArray.AllocatePooledArray((TUnmanagedElement*)Marshal.AllocHGlobal(sizeof(TUnmanagedElement) * managed.Length), managed.Length);
|
||||
handle = GCHandle.Alloc(unmanagedArray);
|
||||
}
|
||||
|
||||
@@ -670,7 +738,7 @@ namespace FlaxEngine
|
||||
|
||||
public void Free()
|
||||
{
|
||||
unmanagedArray.Release();
|
||||
unmanagedArray.FreePooled();
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
@@ -685,7 +753,7 @@ namespace FlaxEngine
|
||||
|
||||
numElements = managed.Length;
|
||||
|
||||
ManagedArray managedArray = ManagedArray.Get((TUnmanagedElement*)Marshal.AllocHGlobal(sizeof(TUnmanagedElement) * managed.Length), managed.Length);
|
||||
ManagedArray managedArray = ManagedArray.AllocatePooledArray((TUnmanagedElement*)Marshal.AllocHGlobal(sizeof(TUnmanagedElement) * managed.Length), managed.Length);
|
||||
IntPtr handle = GCHandle.ToIntPtr(GCHandle.Alloc(managedArray));
|
||||
|
||||
return (TUnmanagedElement*)handle;
|
||||
@@ -721,7 +789,7 @@ namespace FlaxEngine
|
||||
return;
|
||||
|
||||
GCHandle handle = GCHandle.FromIntPtr(new IntPtr(unmanaged));
|
||||
Unsafe.As<ManagedArray>(handle.Target).Release();
|
||||
Unsafe.As<ManagedArray>(handle.Target).FreePooled();
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
@@ -1833,10 +1901,19 @@ namespace FlaxEngine
|
||||
internal static IntPtr NewArray(IntPtr typeHandle, long size)
|
||||
{
|
||||
Type type = Unsafe.As<Type>(GCHandle.FromIntPtr(typeHandle).Target);
|
||||
|
||||
Array arr = ArrayFactory.CreateArray(type, size);
|
||||
ManagedArray managedArray = ManagedArray.Get(arr);
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(managedArray/*, GCHandleType.Weak*/));
|
||||
|
||||
Type marshalledType = ArrayFactory.GetMarshalledType(type);
|
||||
if (marshalledType.IsValueType)
|
||||
{
|
||||
ManagedArray managedArray = ManagedArray.AllocateNewArray(Marshal.AllocHGlobal(Marshal.SizeOf(marshalledType) * (int)size), (int)size, Marshal.SizeOf(marshalledType));
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(managedArray/*, GCHandleType.Weak*/));
|
||||
}
|
||||
else
|
||||
{
|
||||
Array arr = ArrayFactory.CreateArray(type, size);
|
||||
ManagedArray managedArray = ManagedArray.WrapNewArray(arr);
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(managedArray/*, GCHandleType.Weak*/));
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
@@ -1847,7 +1924,7 @@ namespace FlaxEngine
|
||||
return IntPtr.Zero;
|
||||
|
||||
Assert.IsTrue(index >= 0 && index < managedArray.Length);
|
||||
return IntPtr.Add(managedArray.PointerToPinnedArray, size * index);
|
||||
return IntPtr.Add(managedArray.GetPointer, size * index);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
@@ -2037,7 +2114,7 @@ namespace FlaxEngine
|
||||
else if (methodBlob.method.ReturnType == typeof(Type))
|
||||
return GCHandle.ToIntPtr(GetOrAddTypeGCHandle(Unsafe.As<Type>(returnObject)));
|
||||
else if (methodBlob.method.ReturnType == typeof(object[]))
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(ManagedArrayToGCHandleArray(Unsafe.As<object[]>(returnObject))), GCHandleType.Weak));
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As<object[]>(returnObject))), GCHandleType.Weak));
|
||||
else
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(returnObject, GCHandleType.Weak));
|
||||
}
|
||||
@@ -2087,8 +2164,8 @@ namespace FlaxEngine
|
||||
internal static void SetArrayValueReference(IntPtr arrayHandle, IntPtr elementPtr, IntPtr valueHandle)
|
||||
{
|
||||
ManagedArray managedArray = Unsafe.As<ManagedArray>(GCHandle.FromIntPtr(arrayHandle).Target);
|
||||
int index = (int)(elementPtr.ToInt64() - managedArray.PointerToPinnedArray.ToInt64()) / managedArray.ElementSize;
|
||||
managedArray.SetValue(valueHandle, index);
|
||||
int index = (int)(elementPtr.ToInt64() - managedArray.GetPointer.ToInt64()) / managedArray.ElementSize;
|
||||
managedArray.GetSpan<IntPtr>()[index] = valueHandle;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
@@ -2647,7 +2724,7 @@ namespace FlaxEngine
|
||||
else if (method.ReturnType == typeof(Type))
|
||||
return GCHandle.ToIntPtr(GetOrAddTypeGCHandle(Unsafe.As<Type>(returnObject)));
|
||||
else if (method.ReturnType == typeof(object[]))
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(ManagedArrayToGCHandleArray(Unsafe.As<object[]>(returnObject))), GCHandleType.Weak));
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As<object[]>(returnObject))), GCHandleType.Weak));
|
||||
else
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(returnObject, GCHandleType.Weak));
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace FlaxEngine
|
||||
else if (typeof(TRet) == typeof(Type))
|
||||
return returnValue != null ? GCHandle.ToIntPtr(GetOrAddTypeGCHandle(Unsafe.As<Type>(returnValue))) : IntPtr.Zero;
|
||||
else if (typeof(TRet) == typeof(object[]))
|
||||
return returnValue != null ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(ManagedArrayToGCHandleArray(Unsafe.As<object[]>(returnValue))), GCHandleType.Weak)) : IntPtr.Zero;
|
||||
return returnValue != null ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(ManagedArrayToGCHandleArray(Unsafe.As<object[]>(returnValue))), GCHandleType.Weak)) : IntPtr.Zero;
|
||||
else
|
||||
return returnValue != null ? GCHandle.ToIntPtr(GCHandle.Alloc(returnValue, GCHandleType.Weak)) : IntPtr.Zero;
|
||||
}
|
||||
|
||||
@@ -1499,25 +1499,25 @@ namespace Flax.Build.Bindings
|
||||
string originalElementTypeMarshaller = originalElementType + "Marshaller";
|
||||
string internalElementType = $"{originalElementTypeMarshaller}.{originalElementType}Internal";
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.NativeArrayToManagedArray<{originalElementType}, {internalElementType}>(((ManagedArray)GCHandle.FromIntPtr(managed.{fieldInfo.Name}).Target).GetSpan<{internalElementType}>(), {originalElementTypeMarshaller}.ToManaged) : null");
|
||||
toNativeContent.Append($"GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(managed.{fieldInfo.Name}), GCHandleType.Weak))");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = ((ManagedArray)handle.Target).GetSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.Free(value); }} ((ManagedArray)handle.Target).Release(); handle.Free(); }}");
|
||||
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = ((ManagedArray)handle.Target).GetSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.Free(value); }} ((ManagedArray)handle.Target).Release(); handle.Free(); }}");
|
||||
toNativeContent.Append($"GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(managed.{fieldInfo.Name}), GCHandleType.Weak))");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = ((ManagedArray)handle.Target).GetSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.Free(value); }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
|
||||
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = ((ManagedArray)handle.Target).GetSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.Free(value); }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
|
||||
}
|
||||
else if (fieldInfo.Type.GenericArgs[0].IsObjectRef)
|
||||
{
|
||||
// Array elements passed as GCHandles
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<{originalElementType}>((ManagedArray)GCHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(NativeInterop.ManagedArrayToGCHandleArray(managed.{fieldInfo.Name})), GCHandleType.Weak)) : IntPtr.Zero");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).GetSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ GCHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Release(); handle.Free(); }}");
|
||||
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).GetSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ GCHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Release(); handle.Free(); }}");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(NativeInterop.ManagedArrayToGCHandleArray(managed.{fieldInfo.Name})), GCHandleType.Weak)) : IntPtr.Zero");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).GetSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ GCHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
|
||||
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = ((ManagedArray)handle.Target).GetSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ GCHandle.FromIntPtr(ptr).Free(); }} }} ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Blittable array elements
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? ((ManagedArray)GCHandle.FromIntPtr(managed.{fieldInfo.Name}).Target).GetArray<{originalElementType}>() : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.Get(managed.{fieldInfo.Name}), GCHandleType.Weak)) : IntPtr.Zero");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); ((ManagedArray)handle.Target).Release(); handle.Free(); }}");
|
||||
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); ((ManagedArray)handle.Target).Release(); handle.Free(); }}");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? GCHandle.ToIntPtr(GCHandle.Alloc(ManagedArray.WrapNewArray(managed.{fieldInfo.Name}), GCHandleType.Weak)) : IntPtr.Zero");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
|
||||
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ GCHandle handle = GCHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); ((ManagedArray)handle.Target).Free(); handle.Free(); }}");
|
||||
}
|
||||
}
|
||||
else if (fieldInfo.Type.Type == "Version")
|
||||
|
||||
Reference in New Issue
Block a user