wip 2 no leaks

This commit is contained in:
2025-12-21 17:45:31 +02:00
parent 5d45b9ea1c
commit 0973363c64
10 changed files with 666 additions and 58 deletions

View File

@@ -84,6 +84,7 @@ public:
static MString* GetEmpty(MDomain* domain = nullptr);
static MString* New(const char* str, int32 length, MDomain* domain = nullptr);
static MString* New(const Char* str, int32 length, MDomain* domain = nullptr);
static void Free(MString* obj);
static StringView GetChars(MString* obj);
};
@@ -93,6 +94,7 @@ public:
struct FLAXENGINE_API Array
{
static MArray* New(const MClass* elementKlass, int32 length);
static void Free(const MArray* array);
static MClass* GetClass(MClass* elementKlass);
static MClass* GetArrayClass(const MArray* obj);
static int32 GetLength(const MArray* obj);

View File

@@ -49,9 +49,18 @@ struct MConverter
{
MObject* Box(const T& data, const MClass* klass);
void Unbox(T& result, MObject* data);
void FreeManaged(MObject* data);
void ToManagedArray(MArray* result, const Span<T>& data);
void ToNativeArray(Span<T>& result, const MArray* data);
void FreeManaged(MObject* data);
void FreeManagedArray(MArray* array);
};
// Simple array used to pass arrays of blittable data between managed and unmanaged side.
template<typename T>
struct NativeArray
{
T* data;
int32 length;
};
#if USE_NETCORE
@@ -70,6 +79,10 @@ struct MConverter<bool>
Platform::MemoryCopy(&result, MCore::Object::Unbox(data), sizeof(bool));
}
void FreeManaged(MObject* data)
{
}
void ToManagedArray(MArray* result, const Span<bool>& data)
{
Platform::MemoryCopy(MCore::Array::GetAddress(result), data.Get(), data.Length() * sizeof(bool));
@@ -80,8 +93,10 @@ struct MConverter<bool>
Platform::MemoryCopy(result.Get(), MCore::Array::GetAddress(data), result.Length() * sizeof(bool));
}
void FreeManaged(MObject* data)
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
#endif
@@ -115,6 +130,12 @@ struct MConverter<T, typename TEnableIf<TAnd<TIsPODType<T>, TNot<TIsBaseOf<class
{
MCore::GCHandle::Free(*(MGCHandle*)&data);
}
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
// Converter for String.
@@ -163,7 +184,17 @@ struct MConverter<String>
{
//MString* str = (MString*)MCore::Object::Unbox(data);
//MCore::GCHandle::Free(*(MGCHandle*)&str);
MCore::GCHandle::Free(*(MGCHandle*)&data);
MCore::String::Free((MString*)data);
}
void FreeManagedArray(MArray* array)
{
MString** dataPtr = MCore::Array::GetAddress<MString*>(array);
auto length = MCore::Array::GetLength(array);
for (int32 i = 0; i < length; i++)
MCore::String::Free(dataPtr[i]);
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -201,7 +232,17 @@ struct MConverter<StringAnsi>
void FreeManaged(MObject* data)
{
MCore::GCHandle::Free(*(MGCHandle*)&data);
MCore::String::Free((MString*)data);
}
void FreeManagedArray(MArray* array)
{
MString** dataPtr = MCore::Array::GetAddress<MString*>(array);
auto length = MCore::Array::GetLength(array);
for (int32 i = 0; i < length; i++)
MCore::String::Free(dataPtr[i]);
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -211,16 +252,19 @@ struct MConverter<StringView>
{
MObject* Box(const StringView& data, const MClass* klass)
{
PLATFORM_DEBUG_BREAK; // FIXME
return (MObject*)MUtils::ToString(data);
}
void Unbox(StringView& result, MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
result = MUtils::ToString((MString*)data);
}
void ToManagedArray(MArray* result, const Span<StringView>& data)
{
PLATFORM_DEBUG_BREAK; // FIXME
if (data.Length() == 0)
return;
MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*));
@@ -232,6 +276,7 @@ struct MConverter<StringView>
void ToNativeArray(Span<StringView>& result, const MArray* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
MString** dataPtr = MCore::Array::GetAddress<MString*>(data);
for (int32 i = 0; i < result.Length(); i++)
MUtils::ToString(dataPtr[i], result.Get()[i]);
@@ -239,7 +284,19 @@ struct MConverter<StringView>
void FreeManaged(MObject* data)
{
MCore::GCHandle::Free(*(MGCHandle*)&data);
PLATFORM_DEBUG_BREAK; // FIXME
MCore::String::Free((MString*)data);
}
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK; // FIXME
MString** dataPtr = MCore::Array::GetAddress<MString*>(array);
auto length = MCore::Array::GetLength(array);
for (int32 i = 0; i < length; i++)
MCore::String::Free(dataPtr[i]);
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -249,16 +306,19 @@ struct MConverter<Variant>
{
MObject* Box(const Variant& data, const MClass* klass)
{
PLATFORM_DEBUG_BREAK; // FIXME
return MUtils::BoxVariant(data);
}
void Unbox(Variant& result, MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
result = MUtils::UnboxVariant(data);
}
void ToManagedArray(MArray* result, const Span<Variant>& data)
{
PLATFORM_DEBUG_BREAK; // FIXME
if (data.Length() == 0)
return;
MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*));
@@ -270,6 +330,7 @@ struct MConverter<Variant>
void ToNativeArray(Span<Variant>& result, const MArray* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
MObject** dataPtr = MCore::Array::GetAddress<MObject*>(data);
for (int32 i = 0; i < result.Length(); i++)
result.Get()[i] = MUtils::UnboxVariant(dataPtr[i]);
@@ -277,6 +338,14 @@ struct MConverter<Variant>
void FreeManaged(MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
}
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -286,11 +355,13 @@ struct MConverter<T*, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Va
{
MObject* Box(T* data, const MClass* klass)
{
PLATFORM_DEBUG_BREAK; // FIXME
return data ? data->GetOrCreateManagedInstance() : nullptr;
}
void Unbox(T*& result, MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
result = (T*)ScriptingObject::ToNative(data);
}
@@ -314,6 +385,13 @@ struct MConverter<T*, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Va
void FreeManaged(MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
}
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -323,11 +401,13 @@ struct MConverter<T, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Val
{
MObject* Box(const T& data, const MClass* klass)
{
PLATFORM_DEBUG_BREAK; // FIXME
return data.GetOrCreateManagedInstance();
}
void ToManagedArray(MArray* result, const Span<T>& data)
{
PLATFORM_DEBUG_BREAK; // FIXME
if (data.Length() == 0)
return;
MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*));
@@ -339,6 +419,14 @@ struct MConverter<T, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Val
void FreeManaged(MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
}
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -351,16 +439,19 @@ struct MConverter<ScriptingObjectReference<T>>
{
MObject* Box(const ScriptingObjectReference<T>& data, const MClass* klass)
{
PLATFORM_DEBUG_BREAK; // FIXME
return data.GetManagedInstance();
}
void Unbox(ScriptingObjectReference<T>& result, MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
result = (T*)ScriptingObject::ToNative(data);
}
void ToManagedArray(MArray* result, const Span<ScriptingObjectReference<T>>& data)
{
PLATFORM_DEBUG_BREAK; // FIXME
if (data.Length() == 0)
return;
MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*));
@@ -372,6 +463,7 @@ struct MConverter<ScriptingObjectReference<T>>
void ToNativeArray(Span<ScriptingObjectReference<T>>& result, const MArray* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
MObject** dataPtr = MCore::Array::GetAddress<MObject*>(data);
for (int32 i = 0; i < result.Length(); i++)
result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]);
@@ -379,6 +471,14 @@ struct MConverter<ScriptingObjectReference<T>>
void FreeManaged(MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
}
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -391,11 +491,13 @@ struct MConverter<AssetReference<T>>
{
MObject* Box(const AssetReference<T>& data, const MClass* klass)
{
PLATFORM_DEBUG_BREAK; // FIXME
return data.GetManagedInstance();
}
void Unbox(AssetReference<T>& result, MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
result = (T*)ScriptingObject::ToNative(data);
}
@@ -412,6 +514,7 @@ struct MConverter<AssetReference<T>>
void ToNativeArray(Span<AssetReference<T>>& result, const MArray* data)
{
//PLATFORM_DEBUG_BREAK; // FIXME
MObject** dataPtr = MCore::Array::GetAddress<MObject*>(data);
for (int32 i = 0; i < result.Length(); i++)
result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]);
@@ -419,6 +522,13 @@ struct MConverter<AssetReference<T>>
void FreeManaged(MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
}
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -430,6 +540,7 @@ struct MConverter<SoftAssetReference<T>>
{
void ToManagedArray(MArray* result, const Span<SoftAssetReference<T>>& data)
{
//PLATFORM_DEBUG_BREAK; // FIXME
if (data.Length() == 0)
return;
MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*));
@@ -441,6 +552,7 @@ struct MConverter<SoftAssetReference<T>>
void ToNativeArray(Span<SoftAssetReference<T>>& result, const MArray* data)
{
//PLATFORM_DEBUG_BREAK; // FIXME
MObject** dataPtr = MCore::Array::GetAddress<MObject*>(data);
for (int32 i = 0; i < result.Length(); i++)
result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]);
@@ -448,6 +560,14 @@ struct MConverter<SoftAssetReference<T>>
void FreeManaged(MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
}
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -457,6 +577,7 @@ struct MConverter<Array<T>>
{
MObject* Box(const Array<T>& data, const MClass* klass)
{
PLATFORM_DEBUG_BREAK; // FIXME
if (!klass)
return nullptr;
MArray* result = MCore::Array::New(klass->GetElementClass(), data.Count());
@@ -477,6 +598,19 @@ struct MConverter<Array<T>>
void FreeManaged(MObject* data)
{
PLATFORM_DEBUG_BREAK; // FIXME
MArray* array = (MArray*)data;
MConverter<T> converter;
converter.FreeManagedArray(array);
//MCore::Array::Free(array);
//MCore::GCHandle::Free(*(MGCHandle*)&data);
}
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -554,6 +688,16 @@ namespace MUtils
converter.FreeManaged(object);
}
/// <summary>
/// Releases the managed resources of a boxed object.
/// </summary>
template<class T>
void FreeManagedArray(MArray* array)
{
MConverter<T> converter;
converter.FreeManagedArray(array);
}
/// <summary>
/// Links managed array data to the unmanaged BytesContainer.
/// </summary>
@@ -690,6 +834,52 @@ namespace MUtils
}
#if USE_NETCORE
/// <summary>
/// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data.
/// </summary>
/// <param name="data">The input data.</param>
/// <returns>The output array.</returns>
template<typename T>
FORCE_INLINE T* ToNativeArray(const Array<T>& data)
{
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
T* arr = (T*)MCore::GC::AllocateMemory(data.Count() * sizeof(T), true);
Platform::MemoryCopy(arr, data.Get(), data.Count() * sizeof(T));
return arr;
}
/// <summary>
/// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data.
/// </summary>
/// <param name="data">The input data.</param>
/// <returns>The output array.</returns>
template<typename T, typename AllocationType = HeapAllocation>
FORCE_INLINE NativeArray<T> ToNativeArrayWrapper(const Array<T, AllocationType>& data)
{
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<T> arr;
arr.length = data.Count();
arr.data = (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true);
Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T));
return arr;
}
/// <summary>
/// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data.
/// </summary>
/// <param name="data">The input data.</param>
/// <returns>The output array.</returns>
template<typename T>
FORCE_INLINE NativeArray<T> ToNativeArrayWrapper(const Span<T>& data)
{
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<T> arr;
arr.length = data.Length();
arr.data = (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true);
Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T));
return arr;
}
/// <summary>
/// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data.
/// </summary>