_unbox
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:
2025-12-21 20:17:24 +02:00
parent 0973363c64
commit 3008d8037d
12 changed files with 101 additions and 29 deletions

View File

@@ -397,7 +397,8 @@ bool ManagedEditor::HasGameViewportFocus() const
Internal_HasGameViewportFocus = GetClass()->GetMethod("Internal_HasGameViewportFocus");
ASSERT(Internal_HasGameViewportFocus);
}
result = MUtils::Unbox<bool>(Internal_HasGameViewportFocus->Invoke(GetManagedInstance(), nullptr, nullptr), true);
auto invk = Internal_HasGameViewportFocus->Invoke(GetManagedInstance(), nullptr, nullptr);
result = MUtils::Unbox<bool>(invk, true);
}
return result;
}

View File

@@ -962,7 +962,7 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3
else if (!MCore::Type::IsPointer(valueType) && !MCore::Type::IsReference(valueType))
{
if (boxed)
Platform::MemoryCopy(value, MCore::Object::Unbox(boxed), valueSize);
MCore::Object::Unbox(boxed, value);
else
Platform::MemoryClear(value, valueSize);
}

View File

@@ -4301,8 +4301,12 @@ void Variant::CopyStructure(void* src)
if (MANAGED_GC_HANDLE && mclass->IsValueType())
{
MObject* instance = MCore::GCHandle::GetTarget(MANAGED_GC_HANDLE);
void* data = MCore::Object::Unbox(instance);
Platform::MemoryCopy(data, src, mclass->GetInstanceSize());
PLATFORM_DEBUG_BREAK; // FIXME
MCore::GCHandle::Free(MANAGED_GC_HANDLE);
instance = MCore::Object::Box(src, mclass);
MANAGED_GC_HANDLE = *(MGCHandle*)&instance;
//void* data = MCore::Object::Unbox(instance);
//Platform::MemoryCopy(data, src, mclass->GetInstanceSize());
}
}
#endif

View File

@@ -674,8 +674,10 @@ namespace FlaxEngine.Interop
}
/// <summary>
/// Creates a managed copy of the value, and stores it in a boxed reference.
/// Creates a managed converted copy of the unmanaged value, and boxes it in a managed handle.
/// </summary>
/// <param name="typeHandle">A handle to class type.</param>
/// <param name="valuePtr">A pointer to unmanaged value.</param>
[UnmanagedCallersOnly]
internal static ManagedHandle BoxValue(ManagedHandle typeHandle, IntPtr valuePtr)
{
@@ -685,16 +687,17 @@ namespace FlaxEngine.Interop
}
/// <summary>
/// Returns the address of the boxed value type.
/// Writes the unboxed converted value to given address.
/// </summary>
/// <param name="objectHandle">A handle to boxed object.</param>
/// <param name="destinationPtr">The destination address for unboxed value.</param>
[UnmanagedCallersOnly]
internal static IntPtr UnboxValue(ManagedHandle handle)
internal static void UnboxValue(ManagedHandle objectHandle, IntPtr destinationPtr)
{
object value = handle.Target;
object value = objectHandle.Target;
Assert.IsNotNull(value, "Boxed value type can't be null.");
Type type = value.GetType();
if (!type.IsValueType)
return ManagedHandle.ToIntPtr(handle);
return ValueTypeUnboxer.GetPointer(value, type);
MarshalToNative(objectHandle.Target, destinationPtr, type);
}
[UnmanagedCallersOnly]

View File

@@ -194,7 +194,8 @@ CultureInfo MUtils::ToNative(void* value)
if (lcidProperty && lcidProperty->GetGetMethod())
{
MObject* lcidObj = lcidProperty->GetGetMethod()->Invoke(value, nullptr, nullptr);
lcid = *(int32*)MCore::Object::Unbox(lcidObj);
PLATFORM_DEBUG_BREAK;
MCore::Object::Unbox(lcidObj, &lcid);
}
}
#endif

View File

@@ -69,6 +69,7 @@ public:
{
static MObject* Box(void* value, const MClass* klass);
static void* Unbox(MObject* obj);
static void Unbox(MObject* obj, void* dest);
static MObject* New(const MClass* klass);
static void Init(MObject* obj);
static MClass* GetClass(MObject* obj);

View File

@@ -313,7 +313,10 @@ Variant MUtils::UnboxVariant(MObject* value, bool releaseHandle)
MType* mType = klass->GetType();
const MTypes mTypes = MCore::Type::GetType(mType);
void* unboxed = MCore::Object::Unbox(value);
Variant storage;
MCore::Object::Unbox(value, &storage.AsData);
void* unboxed = &storage.AsData;
// Fast type detection for in-built types
switch (mTypes)
@@ -492,13 +495,16 @@ Variant MUtils::UnboxVariant(MObject* value, bool releaseHandle)
// TODO: optimize this for large arrays to prevent multiple AllocStructure calls in Variant::SetType by using computed struct type
for (int32 i = 0; i < array.Count(); i++)
{
PLATFORM_DEBUG_BREAK; // FIXME
auto& a = array[i];
a.SetType(elementType);
void* managed = (byte*)ptr + elementSize * i;
// TODO: optimize structures unboxing to not require MObject* but raw managed value data to prevent additional boxing here
MObject* boxed = MCore::Object::New(elementClass);
Platform::MemoryCopy(MCore::Object::Unbox(boxed), managed, elementSize);
type.Struct.Unbox(a.AsBlob.Data, boxed);
//MObject* boxed = MCore::Object::New(elementClass);
//Variant storage;
MCore::Object::Unbox((MObject*)managed, &a.AsBlob.Data);
//Platform::MemoryCopy(MCore::Object::Unbox(boxed), managed, elementSize);
//type.Struct.Unbox(a.AsBlob.Data, boxed);
}
break;
}
@@ -559,7 +565,8 @@ Variant MUtils::UnboxVariant(MObject* value, bool releaseHandle)
Variant v;
v.Type = MoveTemp(VariantType(VariantType::Enum, fullname));
// TODO: what about 64-bit enum? use enum size with memcpy
v.AsUint64 = *static_cast<uint32*>(MCore::Object::Unbox(value));
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Object::Unbox(value, &v.AsUint64);
if (releaseHandle)
MUtils::FreeManaged<byte>(value);
return v;
@@ -743,9 +750,10 @@ MObject* MUtils::BoxVariant(const Variant& value)
ASSERT(type.Type == ScriptingTypes::Structure);
for (int32 i = 0; i < array.Count(); i++)
{
PLATFORM_DEBUG_BREAK; // FIXME
// TODO: optimize structures boxing to not return MObject* but use raw managed object to prevent additional boxing here
MObject* boxed = type.Struct.Box(array[i].AsBlob.Data);
Platform::MemoryCopy(managedPtr + elementSize * i, MCore::Object::Unbox(boxed), elementSize);
MCore::Object::Unbox(boxed, managedPtr + elementSize * i);
}
break;
}
@@ -1176,7 +1184,9 @@ void* MUtils::VariantToManagedArgPtr(Variant& value, MType* type, bool& failed)
auto& valueType = typeHandle.GetType();
if (valueType.ManagedClass == MCore::Type::GetClass(type))
{
return MCore::Object::Unbox(valueType.Struct.Box(value.AsBlob.Data));
PLATFORM_DEBUG_BREAK; // FIXME
MCore::Object::Unbox(valueType.Struct.Box(value.AsBlob.Data), &value.AsBlob.Data);
return &value.AsBlob.Data;
}
LOG(Error, "Cannot marshal argument of type {0} as {1}", String(valueType.Fullname), MCore::Type::ToString(type));
}
@@ -1187,9 +1197,11 @@ void* MUtils::VariantToManagedArgPtr(Variant& value, MType* type, bool& failed)
const ScriptingTypeHandle typeHandle = Scripting::FindScriptingType(fullname);
if (typeHandle)
{
PLATFORM_DEBUG_BREAK; // FIXME
auto& valueType = typeHandle.GetType();
value.SetType(VariantType(VariantType::Structure, fullname));
return MCore::Object::Unbox(valueType.Struct.Box(value.AsBlob.Data));
MCore::Object::Unbox(valueType.Struct.Box(value.AsBlob.Data), &value.AsBlob.Data);
return &value.AsBlob.Data;
}
}
}

View File

@@ -76,7 +76,7 @@ struct MConverter<bool>
void Unbox(bool& result, MObject* data)
{
if (data)
Platform::MemoryCopy(&result, MCore::Object::Unbox(data), sizeof(bool));
MCore::Object::Unbox(data, &result);
}
void FreeManaged(MObject* data)
@@ -113,7 +113,7 @@ struct MConverter<T, typename TEnableIf<TAnd<TIsPODType<T>, TNot<TIsBaseOf<class
void Unbox(T& result, MObject* data)
{
if (data)
Platform::MemoryCopy(&result, MCore::Object::Unbox(data), sizeof(T));
MCore::Object::Unbox(data, &result);
}
void ToManagedArray(MArray* result, const Span<T>& data)
@@ -678,6 +678,35 @@ namespace MUtils
return result;
}
/// <summary>
/// Unboxes MObject to the native value of the given type.
/// </summary>
///
template<>
inline bool Unbox(MObject* object)
{
MConverter<bool> converter;
int32 result;
converter.Unbox(*(bool*)&result, object);
return result != 0;
}
/// <summary>
/// Unboxes MObject to the native value of the given type.
/// </summary>
/// <param name="object">The object.</param>
/// <param name="releaseHandle">True if boxed managed handle should be released.</param>
template<>
inline bool Unbox(MObject* object, bool releaseHandle)
{
MConverter<bool> converter;
int32 result;
converter.Unbox(*(bool*)&result, object);
if (releaseHandle)
converter.FreeManaged(object);
return result != 0;
}
/// <summary>
/// Releases the managed resources of a boxed object.
/// </summary>

View File

@@ -400,9 +400,14 @@ MObject* MCore::Object::Box(void* value, const MClass* klass)
}
void* MCore::Object::Unbox(MObject* obj)
{
CRASH; // Should not be used anymore
}
void MCore::Object::Unbox(MObject* obj, void* dest)
{
static void* UnboxValuePtr = GetStaticMethodPointer(TEXT("UnboxValue"));
return CallStaticMethod<void*, void*>(UnboxValuePtr, obj);
return CallStaticMethod<void, void*, void*>(UnboxValuePtr, obj, dest);
}
MObject* MCore::Object::New(const MClass* klass)

View File

@@ -738,6 +738,11 @@ void* MCore::Object::Unbox(MObject* obj)
//return mono_object_unbox(obj);
}
void MCore::Object::Unbox(MObject* obj, void* dest)
{
CRASH; // Not applicable
}
MObject* MCore::Object::New(const MClass* klass)
{
return mono_object_new(mono_domain_get(), klass->GetNative());

View File

@@ -80,6 +80,10 @@ void* MCore::Object::Unbox(MObject* obj)
return nullptr;
}
void MCore::Object::Unbox(MObject* obj, void* dest)
{
}
MObject* MCore::Object::New(const MClass* klass)
{
return nullptr;

View File

@@ -2689,14 +2689,20 @@ namespace Flax.Build.Bindings
contents.AppendLine(" }").AppendLine();
// Unboxing structures from managed object to native data
contents.AppendLine(" static void Unbox(void* ptr, MObject* managed)");
contents.AppendLine(" static void Unbox(void* ptr, MObject* data)");
contents.AppendLine(" {");
if (structureInfo.MarshalAs != null)
contents.AppendLine($" MISSING_CODE(\"Boxing native type {structureInfo.Name} as {structureInfo.MarshalAs}\");"); // TODO: impl this
else if (structureInfo.IsPod)
contents.AppendLine($" Platform::MemoryCopy(ptr, MCore::Object::Unbox(managed), sizeof({structureTypeNameNative}));");
contents.AppendLine($" MCore::Object::Unbox(data, ptr);");
//contents.AppendLine($" Platform::MemoryCopy(ptr, MCore::Object::Unbox(data), sizeof({structureTypeNameNative}));");
else
contents.AppendLine($" *({structureTypeNameNative}*)ptr = ToNative(*({GenerateCppManagedWrapperName(structureInfo)}*)MCore::Object::Unbox(managed));");
{
contents.AppendLine($" {GenerateCppManagedWrapperName(structureInfo)} managed;");
contents.AppendLine($" MCore::Object::Unbox(data, &managed);");
contents.AppendLine($" *({structureTypeNameNative}*)ptr = ToNative(managed);");
}
//contents.AppendLine($" *({structureTypeNameNative}*)ptr = ToNative(*({GenerateCppManagedWrapperName(structureInfo)}*)MCore::Object::Unbox(data));");
contents.AppendLine(" }").AppendLine();
}
else
@@ -3238,9 +3244,10 @@ namespace Flax.Build.Bindings
header.AppendFormat(" DLLEXPORT USED void Unbox({0}& result, MObject* data)", fullName).AppendLine();
header.Append(" {").AppendLine();
//header.AppendFormat(" result = ToNative(*reinterpret_cast<{0}*>(MCore::Object::Unbox(data)));", wrapperName).AppendLine();
header.AppendFormat(" auto managed = *reinterpret_cast<{0}*>(MCore::Object::Unbox(data));", wrapperName).AppendLine();
header.AppendFormat(" result = ToNative(managed);", wrapperName).AppendLine();
header.AppendFormat(" ::FreeManaged(managed);", wrapperName).AppendLine();
header.AppendFormat(" {0} managed;", wrapperName).AppendLine();
header.Append(" MCore::Object::Unbox(data, &managed);").AppendLine();
header.Append(" result = ToNative(managed);").AppendLine();
header.Append(" ::FreeManaged(managed);").AppendLine();
header.Append(" }").AppendLine();
header.AppendFormat(" DLLEXPORT USED void ToManagedArray(MArray* result, const Span<{0}>& data)", fullName).AppendLine();