Refactor CoreCLR runtime into explicit dotnet api instead of mocking mono api

Required by platforms that will use mono under the hood for .Net 7
New `USE_CSHARP` define for C# ability
Engine doesn't use `mono_*` apis directly but via MCore/MClass/MMethod/ apis
This commit is contained in:
Wojtek Figat
2023-03-27 17:29:42 +02:00
parent eed2cdfe04
commit 510fc443e8
111 changed files with 17048 additions and 8765 deletions

View File

@@ -17,6 +17,8 @@ protected:
int32 _length = 0;
public:
typedef T CharType;
/// <summary>
/// Finalizes an instance of the <see cref="StringBase"/> class.
/// </summary>

View File

@@ -29,6 +29,8 @@ protected:
}
public:
typedef T CharType;
/// <summary>
/// Gets the specific const character from this string.
/// </summary>

View File

@@ -23,12 +23,10 @@
#include "Engine/Scripting/ScriptingObject.h"
#include "Engine/Scripting/ManagedCLR/MClass.h"
#include "Engine/Scripting/ManagedCLR/MCore.h"
#include "Engine/Scripting/ManagedCLR/MCore.h"
#include "Engine/Scripting/ManagedCLR/MUtils.h"
#include "Engine/Utilities/Crc.h"
#include "Engine/Utilities/StringConverter.h"
#if USE_MONO
#include <mono/metadata/object.h>
#endif
namespace
{
@@ -108,15 +106,14 @@ VariantType::VariantType(Types type, const StringAnsiView& typeName)
}
}
VariantType::VariantType(Types type, _MonoClass* klass)
VariantType::VariantType(Types type, MClass* klass)
{
Type = type;
TypeName = nullptr;
#if USE_MONO
#if USE_CSHARP
if (klass)
{
MString typeName;
MUtils::GetClassFullname(klass, typeName);
const StringAnsi& typeName = klass->GetFullName();
const int32 length = typeName.Length();
TypeName = static_cast<char*>(Allocator::Allocate(length + 1));
Platform::MemoryCopy(TypeName, typeName.Get(), length);
@@ -166,7 +163,7 @@ VariantType::VariantType(const StringAnsiView& typeName)
}
// Try using managed class
#if USE_MONO
#if USE_CSHARP
if (const auto mclass = Scripting::FindClass(typeName))
{
new(this) VariantType(ManagedObject, typeName);
@@ -615,21 +612,21 @@ Variant::Variant(Asset* v)
}
}
#if USE_MONO
#if USE_CSHARP
Variant::Variant(_MonoObject* v)
: Type(VariantType::ManagedObject, v ? mono_object_get_class(v) : nullptr)
Variant::Variant(MObject* v)
: Type(VariantType::ManagedObject, v ? MCore::Object::GetClass(v) : nullptr)
{
#if USE_NETCORE
AsUint64 = v ? MUtils::NewGCHandle(v, true) : 0;
AsUint64 = v ? MCore::GCHandle::New(v, true) : 0;
#else
AsUint = v ? MUtils::NewGCHandle(v, true) : 0;
AsUint = v ? MCore::GCHandle::New(v, true) : 0;
#endif
}
#else
Variant::Variant(_MonoObject* v)
Variant::Variant(MObject* v)
: Type(VariantType::ManagedObject, nullptr)
{
AsUint = 0;
@@ -964,13 +961,12 @@ Variant::~Variant()
case VariantType::ManagedObject:
#if USE_NETCORE
if (AsUint64)
MUtils::FreeGCHandle(AsUint64);
break;
MCore::GCHandle::Free(AsUint64);
#elif USE_MONO
if (AsUint)
MUtils::FreeGCHandle(AsUint);
break;
MCore::GCHandle::Free(AsUint);
#endif
break;
default: ;
}
}
@@ -1098,9 +1094,9 @@ Variant& Variant::operator=(const Variant& other)
break;
case VariantType::ManagedObject:
#if USE_NETCORE
AsUint64 = other.AsUint64 ? MUtils::NewGCHandle(MUtils::GetGCHandleTarget(other.AsUint64), true) : 0;
AsUint64 = other.AsUint64 ? MCore::GCHandle::New(MCore::GCHandle::GetTarget(other.AsUint64), true) : 0;
#elif USE_MONO
AsUint = other.AsUint ? MUtils::NewGCHandle(MUtils::GetGCHandleTarget(other.AsUint), true) : 0;
AsUint = other.AsUint ? MCore::GCHandle::New(MCore::GCHandle::GetTarget(other.AsUint), true) : 0;
#endif
break;
case VariantType::Null:
@@ -1226,9 +1222,13 @@ bool Variant::operator==(const Variant& other) const
return false;
return AsBlob.Length == other.AsBlob.Length && StringUtils::Compare(static_cast<const char*>(AsBlob.Data), static_cast<const char*>(other.AsBlob.Data), AsBlob.Length - 1) == 0;
case VariantType::ManagedObject:
#if USE_MONO
#if USE_NETCORE
// TODO: invoke C# Equality logic?
return AsUint == other.AsUint || MUtils::GetGCHandleTarget(AsUint) == MUtils::GetGCHandleTarget(other.AsUint);
return AsUint64 == other.AsUint64 || MCore::GCHandle::GetTarget(AsUint64) == MCore::GCHandle::GetTarget(other.AsUint64);
#elif USE_MONO
return AsUint == other.AsUint || MCore::GCHandle::GetTarget(AsUint) == MCore::GCHandle::GetTarget(other.AsUint);
#else
return nullptr;
#endif
default:
return false;
@@ -1320,9 +1320,11 @@ Variant::operator bool() const
return AsAsset != nullptr;
case VariantType::ManagedObject:
#if USE_NETCORE
return AsUint64 != 0 && MUtils::GetGCHandleTarget(AsUint64) != nullptr;
return AsUint64 != 0 && MCore::GCHandle::GetTarget(AsUint64) != nullptr;
#elif USE_MONO
return AsUint != 0 && MUtils::GetGCHandleTarget(AsUint) != nullptr;
return AsUint != 0 && MCore::GCHandle::GetTarget(AsUint) != nullptr;
#else
return nullptr;
#endif
default:
return false;
@@ -1592,9 +1594,11 @@ Variant::operator void*() const
return AsBlob.Data;
case VariantType::ManagedObject:
#if USE_NETCORE
return AsUint64 ? MUtils::GetGCHandleTarget(AsUint64) : nullptr;
return AsUint64 ? MCore::GCHandle::GetTarget(AsUint64) : nullptr;
#elif USE_MONO
return AsUint ? MUtils::GetGCHandleTarget(AsUint) : nullptr;
return AsUint ? MCore::GCHandle::GetTarget(AsUint) : nullptr;
#else
return nullptr;
#endif
default:
return nullptr;
@@ -1636,12 +1640,12 @@ Variant::operator ScriptingObject*() const
}
}
Variant::operator _MonoObject*() const
Variant::operator MObject*() const
{
#if USE_NETCORE
return Type.Type == VariantType::ManagedObject && AsUint64 ? MUtils::GetGCHandleTarget(AsUint64) : nullptr;
return Type.Type == VariantType::ManagedObject && AsUint64 ? MCore::GCHandle::GetTarget(AsUint64) : nullptr;
#elif USE_MONO
return Type.Type == VariantType::ManagedObject && AsUint ? MUtils::GetGCHandleTarget(AsUint) : nullptr;
return Type.Type == VariantType::ManagedObject && AsUint ? MCore::GCHandle::GetTarget(AsUint) : nullptr;
#else
return nullptr;
#endif
@@ -2356,12 +2360,10 @@ void Variant::SetType(const VariantType& type)
case VariantType::ManagedObject:
#if USE_NETCORE
if (AsUint64)
MUtils::FreeGCHandle(AsUint64);
break;
MCore::GCHandle::Free(AsUint64);
#elif USE_MONO
if (AsUint)
MUtils::FreeGCHandle(AsUint);
break;
MCore::GCHandle::Free(AsUint);
#endif
break;
default: ;
@@ -2471,12 +2473,10 @@ void Variant::SetType(VariantType&& type)
case VariantType::ManagedObject:
#if USE_NETCORE
if (AsUint64)
MUtils::FreeGCHandle(AsUint64);
break;
MCore::GCHandle::Free(AsUint64);
#elif USE_MONO
if (AsUint)
MUtils::FreeGCHandle(AsUint);
break;
MCore::GCHandle::Free(AsUint);
#endif
break;
default: ;
@@ -2652,17 +2652,17 @@ void Variant::SetObject(ScriptingObject* object)
object->Deleted.Bind<Variant, &Variant::OnObjectDeleted>(this);
}
void Variant::SetManagedObject(_MonoObject* object)
void Variant::SetManagedObject(MObject* object)
{
#if USE_MONO
#if USE_CSHARP
if (object)
{
if (Type.Type != VariantType::ManagedObject)
SetType(VariantType(VariantType::ManagedObject, mono_object_get_class(object)));
SetType(VariantType(VariantType::ManagedObject, MCore::Object::GetClass(object)));
#if USE_NETCORE
AsUint64 = MUtils::NewGCHandle(object, true);
AsUint64 = MCore::GCHandle::New(object, true);
#else
AsUint = MUtils::NewGCHandle(object, true);
AsUint = MCore::GCHandle::New(object, true);
#endif
}
else
@@ -2783,9 +2783,11 @@ String Variant::ToString() const
return String((const char*)AsBlob.Data, AsBlob.Length ? AsBlob.Length - 1 : 0);
case VariantType::ManagedObject:
#if USE_NETCORE
return AsUint64 ? String(MUtils::ToString(mono_object_to_string(MUtils::GetGCHandleTarget(AsUint64), nullptr))) : TEXT("null");
return AsUint64 ? String(MUtils::ToString(MCore::Object::ToString(MCore::GCHandle::GetTarget(AsUint64)))) : TEXT("null");
#elif USE_MONO
return AsUint ? String(MUtils::ToString(mono_object_to_string(MUtils::GetGCHandleTarget(AsUint), nullptr))) : TEXT("null");
return AsUint ? String(MUtils::ToString(MCore::Object::ToString(MCore::GCHandle::GetTarget(AsUint)))) : TEXT("null");
#else
return String::Empty;
#endif
default:
return String::Empty;
@@ -3688,17 +3690,17 @@ void Variant::AllocStructure()
AsBlob.Data = Allocator::Allocate(AsBlob.Length);
*((int16*)AsBlob.Data) = 0;
}
#if USE_MONO
#if USE_CSHARP
else if (const auto mclass = Scripting::FindClass(typeName))
{
// Fallback to C#-only types
MCore::AttachThread();
auto instance = mclass->CreateInstance();
MCore::Thread::Attach();
MObject* instance = mclass->CreateInstance();
if (instance)
{
#if 0
void* data = mono_object_unbox(instance);
int32 instanceSize = mono_class_instance_size(mclass->GetNative());
void* data = MCore::Object::Unbox(instance);
int32 instanceSize = mclass->GetInstanceSize();
AsBlob.Length = instanceSize - (int32)((uintptr)data - (uintptr)instance);
AsBlob.Data = Allocator::Allocate(AsBlob.Length);
Platform::MemoryCopy(AsBlob.Data, data, AsBlob.Length);
@@ -3706,9 +3708,9 @@ void Variant::AllocStructure()
Type.Type = VariantType::ManagedObject;
#if USE_NETCORE
AsUint64 = MUtils::NewGCHandle(instance, true);
AsUint64 = MCore::GCHandle::New(instance, true);
#else
AsUint = MUtils::NewGCHandle(instance, true);
AsUint = MCore::GCHandle::New(instance, true);
#endif
#endif
}
@@ -3802,9 +3804,11 @@ uint32 GetHash(const Variant& key)
return GetHash((const char*)key.AsBlob.Data);
case VariantType::ManagedObject:
#if USE_NETCORE
return key.AsUint64 ? (uint32)mono_object_hash(MUtils::GetGCHandleTarget(key.AsUint64)) : 0;
return key.AsUint64 ? (uint32)MCore::Object::GetHashCode(MCore::GCHandle::GetTarget(key.AsUint64)) : 0;
#elif USE_MONO
return key.AsUint ? (uint32)mono_object_hash(MUtils::GetGCHandleTarget(key.AsUint)) : 0;
return key.AsUint ? (uint32)MCore::Object::GetHashCode(MCore::GCHandle::GetTarget(key.AsUint)) : 0;
#else
return 0;
#endif
default:
return 0;

View File

@@ -3,10 +3,9 @@
#pragma once
#include "Engine/Core/Types/String.h"
#include "Engine/Scripting/Types.h"
class Asset;
class ScriptingObject;
struct ScriptingType;
struct Transform;
struct CommonValue;
template<typename T>
@@ -105,7 +104,7 @@ public:
explicit VariantType(Types type, const StringView& typeName);
explicit VariantType(Types type, const StringAnsiView& typeName);
explicit VariantType(Types type, struct _MonoClass* klass);
explicit VariantType(Types type, MClass* klass);
explicit VariantType(const StringAnsiView& typeName);
VariantType(const VariantType& other);
VariantType(VariantType&& other) noexcept;
@@ -215,7 +214,7 @@ public:
Variant(void* v);
Variant(ScriptingObject* v);
Variant(Asset* v);
Variant(struct _MonoObject* v);
Variant(MObject* v);
Variant(const StringView& v);
Variant(const StringAnsiView& v);
Variant(const Char* v);
@@ -296,7 +295,7 @@ public:
explicit operator StringView() const; // Returned StringView, if not empty, is guaranteed to point to a null terminated buffer.
explicit operator StringAnsiView() const; // Returned StringView, if not empty, is guaranteed to point to a null terminated buffer.
explicit operator ScriptingObject*() const;
explicit operator struct _MonoObject*() const;
explicit operator MObject*() const;
explicit operator Asset*() const;
explicit operator Float2() const;
explicit operator Float3() const;
@@ -356,7 +355,7 @@ public:
void SetBlob(int32 length);
void SetBlob(const void* data, int32 length);
void SetObject(ScriptingObject* object);
void SetManagedObject(struct _MonoObject* object);
void SetManagedObject(MObject* object);
void SetAsset(Asset* asset);
String ToString() const;