initial nativestring and nativearray marshalling
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled

This commit is contained in:
2026-01-03 16:00:55 +02:00
parent c7326ea483
commit 7088ce8742
25 changed files with 1958 additions and 341 deletions

View File

@@ -41,6 +41,118 @@ namespace
}
}
#if USE_NETCORE
StringView MUtils::ToString(MString* str)
{
if (str == nullptr)
return StringView::Empty;
return StringView(*(String*)str);
}
StringAnsi MUtils::ToStringAnsi(MString* str)
{
if (str == nullptr)
return StringAnsi::Empty;
return StringAnsi(*(String*)str);
}
void MUtils::ToString(MString* str, String& result)
{
if (str)
{
const StringView chars = StringView(*(String*)str);
result.Set(chars.Get(), chars.Length());
}
else
result.Clear();
}
void MUtils::ToString(MString* str, StringView& result)
{
if (str)
result = StringView(*(String*)str);
else
result = StringView();
}
void MUtils::ToString(MString* str, Variant& result)
{
result.SetString(str ? StringView(*(String*)str) : StringView::Empty);
}
void MUtils::ToString(MString* str, StringAnsi& result)
{
if (str)
{
const StringView chars = StringView(*(String*)str);
result.Set(chars.Get(), chars.Length());
}
else
result.Clear();
}
MString* MUtils::ToString(const char* str)
{
CRASH;
if (str == nullptr || *str == 0)
return (MString*)(New<String>());
return (MString*)(New<String>(str, StringUtils::Length(str)));
}
MString* MUtils::ToString(const StringAnsi& str)
{
CRASH;
const int32 len = str.Length();
if (len <= 0)
return (MString*)(New<String>());
return (MString*)(New<String>(str.Get(), len));
}
MString* MUtils::ToString(const String& str)
{
CRASH;
const int32 len = str.Length();
if (len <= 0)
return (MString*)(New<String>());
return (MString*)(New<String>(str.Get(), len));
}
MString* MUtils::ToString(const String& str, MDomain* domain)
{
CRASH;
const int32 len = str.Length();
if (len <= 0)
return (MString*)(New<String>());
return (MString*)(New<String>(str.Get(), len));
}
MString* MUtils::ToString(const StringAnsiView& str)
{
CRASH;
const int32 len = str.Length();
if (len <= 0)
return (MString*)(New<String>());
return (MString*)(New<String>(str.Get(), len));
}
MString* MUtils::ToString(const StringView& str)
{
CRASH;
const int32 len = str.Length();
if (len <= 0)
return (MString*)(New<String>());
return (MString*)(New<String>(str.Get(), len));
}
MString* MUtils::ToString(const StringView& str, MDomain* domain)
{
CRASH;
const int32 len = str.Length();
if (len <= 0)
return (MString*)(New<String>());
return (MString*)(New<String>(str.Get(), len));
}
#else
StringView MUtils::ToString(MString* str)
{
if (str == nullptr)
@@ -144,6 +256,7 @@ MString* MUtils::ToString(const StringView& str, MDomain* domain)
return MCore::String::GetEmpty(domain);
return MCore::String::New(str.Get(), len, domain);
}
#endif
ScriptingTypeHandle MUtils::UnboxScriptingTypeHandle(MTypeObject* value)
{

View File

@@ -85,6 +85,41 @@ struct NativeArray
}
};
/// <summary>
/// A simple POD type Span used with interop between managed and unmanaged sides.
/// </summary>
template<typename T>
struct NativeSpan
{
public:
T* Data;
int32 Length;
public:
static NativeSpan<T> AsSpan(T* data, int32 length)
{
return { data, length };
}
};
template<typename T>
NativeSpan<T> ToNativeSpan(const T* data, int32 length)
{
return { data, length };
}
template<typename T>
NativeSpan<T> ToNativeSpan(const Array<T>& array)
{
return { array.Get(), array.Count() };
}
template<typename T>
NativeSpan<T> ToNativeSpan(const Span<T>& span)
{
return { span.Get(), span.Length() };
}
#if USE_NETCORE
// Special case for boolean values, the handles are fixed and should not be removed
template<>
@@ -128,7 +163,7 @@ struct MConverter<bool>
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
#endif
@@ -176,7 +211,7 @@ struct MConverter<T, typename TEnableIf<TAnd<TIsPODType<T>, TNot<TIsBaseOf<class
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -241,12 +276,13 @@ struct MConverter<String>
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK;
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);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -299,12 +335,13 @@ struct MConverter<StringAnsi>
void FreeManagedArray(MArray* array)
{
PLATFORM_DEBUG_BREAK;
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);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -368,7 +405,7 @@ struct MConverter<StringView>
for (int32 i = 0; i < length; i++)
MCore::String::Free(dataPtr[i]);
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -427,7 +464,7 @@ struct MConverter<Variant>
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -485,7 +522,6 @@ struct MConverter<T*, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Va
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -540,7 +576,7 @@ struct MConverter<T, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Val
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -602,7 +638,7 @@ struct MConverter<ScriptingObjectReference<T>>
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -663,7 +699,7 @@ struct MConverter<AssetReference<T>>
void FreeManagedArray(MArray* array)
{
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -725,7 +761,7 @@ struct MConverter<SoftAssetReference<T>>
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -778,7 +814,7 @@ struct MConverter<Array<T>>
{
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Array::Free(array);
MCore::GCHandle::Free(*(MGCHandle*)&array);
//MCore::GCHandle::Free(*(MGCHandle*)&array);
}
};
@@ -1031,6 +1067,27 @@ namespace MUtils
}
#if USE_NETCORE
/// <summary>
///
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
FORCE_INLINE String ToNativeString(const StringAnsi& str)
{
return String(str);
}
/// <summary>
///
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
FORCE_INLINE String ToNativeString(const StringAnsiView& str)
{
return String(str);
}
/// <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>
@@ -1040,7 +1097,7 @@ namespace MUtils
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);
T* arr = (T*)MCore::GC::AllocateMemory(data.Count() * sizeof(T), false);
Platform::MemoryCopy(arr, data.Get(), data.Count() * sizeof(T));
return arr;
}
@@ -1116,7 +1173,7 @@ namespace MUtils
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<U> arr;
arr.length = data.Length();
arr.data = arr.length > 0 ? (U*)MCore::GC::AllocateMemory(arr.length * sizeof(U), true) : nullptr;
arr.data = arr.length > 0 ? (U*)MCore::GC::AllocateMemory(arr.length * sizeof(U), false) : nullptr;
// Convert to managed
MConverter<T, U> converter;
@@ -1136,7 +1193,7 @@ namespace MUtils
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<T> arr;
arr.length = data.Length();
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr;
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), false) : nullptr;
// Convert to managed
MConverter<T> converter;
@@ -1188,7 +1245,7 @@ namespace MUtils
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<T> arr;
arr.length = data.Length();
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr;
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), false) : nullptr;
// Convert to managed
MConverter<T, U> converter;
@@ -1208,7 +1265,7 @@ namespace MUtils
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<T> arr;
arr.length = data.Length();
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr;
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), false) : nullptr;
Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T));
return arr;
}
@@ -1239,7 +1296,7 @@ namespace MUtils
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<T> arr;
arr.length = data.Length();
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr;
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), false) : nullptr;
//Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T));
// Convert to managed
@@ -1261,7 +1318,7 @@ namespace MUtils
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<T> arr;
arr.length = data.Length();
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr;
arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), false) : nullptr;
Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T));
return arr;
}
@@ -1302,7 +1359,7 @@ namespace MUtils
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
NativeArray<MObject*> arr;
arr.length = data.Length();
arr.data = arr.length > 0 ? (MObject**)MCore::GC::AllocateMemory(arr.length * sizeof(MObject*), true) : nullptr;
arr.data = arr.length > 0 ? (MObject**)MCore::GC::AllocateMemory(arr.length * sizeof(MObject*), false) : nullptr;
// Convert to managed
MConverter<T> converter;
@@ -1320,7 +1377,7 @@ namespace MUtils
FORCE_INLINE bool* ToBoolArray(const Array<bool>& data)
{
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
bool* arr = (bool*)MCore::GC::AllocateMemory(data.Count() * sizeof(bool), true);
bool* arr = (bool*)MCore::GC::AllocateMemory(data.Count() * sizeof(bool), false);
memcpy(arr, data.Get(), data.Count() * sizeof(bool));
return arr;
}
@@ -1334,7 +1391,7 @@ namespace MUtils
FORCE_INLINE bool* ToBoolArray(const BitArray<AllocationType>& data)
{
// System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer
bool* arr = (bool*)MCore::GC::AllocateMemory(data.Count() * sizeof(bool), true);
bool* arr = (bool*)MCore::GC::AllocateMemory(data.Count() * sizeof(bool), false);
for (int i = 0; i < data.Count(); i++)
arr[i] = data[i];
return arr;