From a630575ab6e1c3ea19fefef8cf6bbaebb0e69e09 Mon Sep 17 00:00:00 2001 From: Andrei Gagua Date: Thu, 10 Sep 2026 06:25:26 +0200 Subject: [PATCH] Move out `ManagedDictionary` impl from header file #4120 --- .../Scripting/Internal/ManagedDictionary.cpp | 163 ++++++++++++++++++ .../Scripting/Internal/ManagedDictionary.h | 162 +---------------- Source/Engine/Scripting/ManagedCLR/MUtils.cpp | 3 + 3 files changed, 172 insertions(+), 156 deletions(-) diff --git a/Source/Engine/Scripting/Internal/ManagedDictionary.cpp b/Source/Engine/Scripting/Internal/ManagedDictionary.cpp index d2f74e054..b3de77e85 100644 --- a/Source/Engine/Scripting/Internal/ManagedDictionary.cpp +++ b/Source/Engine/Scripting/Internal/ManagedDictionary.cpp @@ -3,6 +3,12 @@ #include "ManagedDictionary.h" #if USE_CSHARP +#include "Engine/Scripting/BinaryModule.h" +#include "Engine/Scripting/ManagedCLR/MClass.h" +#include "Engine/Scripting/ManagedCLR/MMethod.h" +#include "Engine/Scripting/ManagedCLR/MAssembly.h" +#include "Engine/Scripting/ManagedCLR/MException.h" +#include "Engine/Scripting/Internal/StdTypesContainer.h" Dictionary ManagedDictionary::CachedTypes; #if !USE_MONO_AOT ManagedDictionary::MakeGenericTypeThunk ManagedDictionary::MakeGenericType; @@ -15,4 +21,161 @@ MMethod* ManagedDictionary::CreateInstance; MMethod* ManagedDictionary::AddDictionaryItem; MMethod* ManagedDictionary::GetDictionaryKeys; #endif + +ManagedDictionary::ManagedDictionary(MObject* instance) +{ + Instance = instance; + +#if !USE_MONO_AOT + // Cache the thunks of the dictionary helper methods + if (MakeGenericType == nullptr) + { + MClass* scriptingClass = Scripting::GetStaticClass(); + CHECK(scriptingClass); + + MMethod* makeGenericTypeMethod = scriptingClass->GetMethod("MakeGenericType", 2); + CHECK(makeGenericTypeMethod); + MakeGenericType = (MakeGenericTypeThunk)makeGenericTypeMethod->GetThunk(); + + MMethod* createInstanceMethod = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2); + CHECK(createInstanceMethod); + CreateInstance = (CreateInstanceThunk)createInstanceMethod->GetThunk(); + + MMethod* addDictionaryItemMethod = scriptingClass->GetMethod("AddDictionaryItem", 3); + CHECK(addDictionaryItemMethod); + AddDictionaryItem = (AddDictionaryItemThunk)addDictionaryItemMethod->GetThunk(); + + MMethod* getDictionaryKeysItemMethod = scriptingClass->GetMethod("GetDictionaryKeys", 1); + CHECK(getDictionaryKeysItemMethod); + GetDictionaryKeys = (GetDictionaryKeysThunk)getDictionaryKeysItemMethod->GetThunk(); + } +#else + if (MakeGenericType == nullptr) + { + MClass* scriptingClass = Scripting::GetStaticClass(); + CHECK(scriptingClass); + + MakeGenericType = scriptingClass->GetMethod("MakeGenericType", 2); + CHECK(MakeGenericType); + + CreateInstance = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2); + CHECK(CreateInstance); + + AddDictionaryItem = scriptingClass->GetMethod("AddDictionaryItem", 3); + CHECK(AddDictionaryItem); + + GetDictionaryKeys = scriptingClass->GetMethod("GetDictionaryKeys", 1); + CHECK(GetDictionaryKeys); + } +#endif +} + +MTypeObject* ManagedDictionary::GetClass(MType* keyType, MType* valueType) +{ + // Check if the generic type was generated earlier + KeyValueType cacheKey = { keyType, valueType }; + MTypeObject* dictionaryType; + if (CachedTypes.TryGet(cacheKey, dictionaryType)) + return dictionaryType; + + MTypeObject* genericType = MUtils::GetType(StdTypesContainer::Instance()->DictionaryClass); +#if USE_NETCORE + MArray* genericArgs = MCore::Array::New(MCore::TypeCache::IntPtr, 2); +#else + MArray* genericArgs = MCore::Array::New(MCore::TypeCache::Object, 2); +#endif + MTypeObject** genericArgsPtr = MCore::Array::GetAddress(genericArgs); + genericArgsPtr[0] = INTERNAL_TYPE_GET_OBJECT(keyType); + genericArgsPtr[1] = INTERNAL_TYPE_GET_OBJECT(valueType); + + MObject* exception = nullptr; +#if !USE_MONO_AOT + dictionaryType = MakeGenericType(nullptr, genericType, genericArgs, &exception); +#else + void* params[2]; + params[0] = genericType; + params[1] = genericArgs; + dictionaryType = (MTypeObject*)MakeGenericType->Invoke(nullptr, params, &exception); +#endif + if (exception) + { + MException ex(exception); + ex.Log(LogType::Error, TEXT("")); + return nullptr; + } + CachedTypes.Add(cacheKey, dictionaryType); + return dictionaryType; +} + +ManagedDictionary ManagedDictionary::New(MType* keyType, MType* valueType) +{ + ManagedDictionary result; + MTypeObject* dictionaryType = GetClass(keyType, valueType); + if (!dictionaryType) + return result; + + MObject* exception = nullptr; +#if !USE_MONO_AOT + MObject* instance = CreateInstance(nullptr, dictionaryType, nullptr, &exception); +#else + void* params[2]; + params[0] = dictionaryType; + params[1] = nullptr; + MObject* instance = CreateInstance->Invoke(nullptr, params, &exception); +#endif + if (exception) + { + MException ex(exception); + ex.Log(LogType::Error, TEXT("")); + return result; + } + + result.Instance = instance; + return result; +} + +void ManagedDictionary::Add(MObject* key, MObject* value) +{ + CHECK(Instance); + + MObject* exception = nullptr; +#if !USE_MONO_AOT + AddDictionaryItem(nullptr, Instance, key, value, &exception); +#else + void* params[3]; + params[0] = Instance; + params[1] = key; + params[2] = value; + AddDictionaryItem->Invoke(Instance, params, &exception); +#endif + if (exception) + { + MException ex(exception); + ex.Log(LogType::Error, TEXT("")); + } +} + +MArray* ManagedDictionary::GetKeys() const +{ + CHECK_RETURN(Instance, nullptr); +#if !USE_MONO_AOT + return GetDictionaryKeys(nullptr, Instance, nullptr); +#else + void* params[1]; + params[0] = Instance; + return (MArray*)GetDictionaryKeys->Invoke(nullptr, params, nullptr); +#endif +} + +MObject* ManagedDictionary::GetValue(MObject* key) const +{ + CHECK_RETURN(Instance, nullptr); + MClass* klass = MCore::Object::GetClass(Instance); + MMethod* getItemMethod = klass->GetMethod("System.Collections.IDictionary.get_Item", 1); + CHECK_RETURN(getItemMethod, nullptr); + void* params[1]; + params[0] = key; + return getItemMethod->Invoke(Instance, params, nullptr); +} + #endif diff --git a/Source/Engine/Scripting/Internal/ManagedDictionary.h b/Source/Engine/Scripting/Internal/ManagedDictionary.h index 5e2638af7..1707aa6d4 100644 --- a/Source/Engine/Scripting/Internal/ManagedDictionary.h +++ b/Source/Engine/Scripting/Internal/ManagedDictionary.h @@ -5,13 +5,7 @@ #include "Engine/Core/Log.h" #include "Engine/Scripting/Scripting.h" #if USE_CSHARP -#include "Engine/Scripting/BinaryModule.h" #include "Engine/Scripting/ManagedCLR/MUtils.h" -#include "Engine/Scripting/ManagedCLR/MClass.h" -#include "Engine/Scripting/ManagedCLR/MMethod.h" -#include "Engine/Scripting/ManagedCLR/MAssembly.h" -#include "Engine/Scripting/ManagedCLR/MException.h" -#include "Engine/Scripting/Internal/StdTypesContainer.h" #include "Engine/Core/Collections/Dictionary.h" /// @@ -57,53 +51,7 @@ private: public: MObject* Instance; - ManagedDictionary(MObject* instance = nullptr) - { - Instance = instance; - -#if !USE_MONO_AOT - // Cache the thunks of the dictionary helper methods - if (MakeGenericType == nullptr) - { - MClass* scriptingClass = Scripting::GetStaticClass(); - CHECK(scriptingClass); - - MMethod* makeGenericTypeMethod = scriptingClass->GetMethod("MakeGenericType", 2); - CHECK(makeGenericTypeMethod); - MakeGenericType = (MakeGenericTypeThunk)makeGenericTypeMethod->GetThunk(); - - MMethod* createInstanceMethod = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2); - CHECK(createInstanceMethod); - CreateInstance = (CreateInstanceThunk)createInstanceMethod->GetThunk(); - - MMethod* addDictionaryItemMethod = scriptingClass->GetMethod("AddDictionaryItem", 3); - CHECK(addDictionaryItemMethod); - AddDictionaryItem = (AddDictionaryItemThunk)addDictionaryItemMethod->GetThunk(); - - MMethod* getDictionaryKeysItemMethod = scriptingClass->GetMethod("GetDictionaryKeys", 1); - CHECK(getDictionaryKeysItemMethod); - GetDictionaryKeys = (GetDictionaryKeysThunk)getDictionaryKeysItemMethod->GetThunk(); - } -#else - if (MakeGenericType == nullptr) - { - MClass* scriptingClass = Scripting::GetStaticClass(); - CHECK(scriptingClass); - - MakeGenericType = scriptingClass->GetMethod("MakeGenericType", 2); - CHECK(MakeGenericType); - - CreateInstance = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2); - CHECK(CreateInstance); - - AddDictionaryItem = scriptingClass->GetMethod("AddDictionaryItem", 3); - CHECK(AddDictionaryItem); - - GetDictionaryKeys = scriptingClass->GetMethod("GetDictionaryKeys", 1); - CHECK(GetDictionaryKeys); - } -#endif - } + ManagedDictionary(MObject* instance = nullptr); template static MObject* ToManaged(const Dictionary& data, MType* keyType, MType* valueType) @@ -154,113 +102,15 @@ public: return result; } - static MTypeObject* GetClass(MType* keyType, MType* valueType) - { - // Check if the generic type was generated earlier - KeyValueType cacheKey = { keyType, valueType }; - MTypeObject* dictionaryType; - if (CachedTypes.TryGet(cacheKey, dictionaryType)) - return dictionaryType; + static MTypeObject* GetClass(MType* keyType, MType* valueType); - MTypeObject* genericType = MUtils::GetType(StdTypesContainer::Instance()->DictionaryClass); -#if USE_NETCORE - MArray* genericArgs = MCore::Array::New(MCore::TypeCache::IntPtr, 2); -#else - MArray* genericArgs = MCore::Array::New(MCore::TypeCache::Object, 2); -#endif - MTypeObject** genericArgsPtr = MCore::Array::GetAddress(genericArgs); - genericArgsPtr[0] = INTERNAL_TYPE_GET_OBJECT(keyType); - genericArgsPtr[1] = INTERNAL_TYPE_GET_OBJECT(valueType); + static ManagedDictionary New(MType* keyType, MType* valueType); - MObject* exception = nullptr; -#if !USE_MONO_AOT - dictionaryType = MakeGenericType(nullptr, genericType, genericArgs, &exception); -#else - void* params[2]; - params[0] = genericType; - params[1] = genericArgs; - dictionaryType = (MTypeObject*)MakeGenericType->Invoke(nullptr, params, &exception); -#endif - if (exception) - { - MException ex(exception); - ex.Log(LogType::Error, TEXT("")); - return nullptr; - } - CachedTypes.Add(cacheKey, dictionaryType); - return dictionaryType; - } + void Add(MObject* key, MObject* value); - static ManagedDictionary New(MType* keyType, MType* valueType) - { - ManagedDictionary result; - MTypeObject* dictionaryType = GetClass(keyType, valueType); - if (!dictionaryType) - return result; + MArray* GetKeys() const; - MObject* exception = nullptr; -#if !USE_MONO_AOT - MObject* instance = CreateInstance(nullptr, dictionaryType, nullptr, &exception); -#else - void* params[2]; - params[0] = dictionaryType; - params[1] = nullptr; - MObject* instance = CreateInstance->Invoke(nullptr, params, &exception); -#endif - if (exception) - { - MException ex(exception); - ex.Log(LogType::Error, TEXT("")); - return result; - } - - result.Instance = instance; - return result; - } - - void Add(MObject* key, MObject* value) - { - CHECK(Instance); - - MObject* exception = nullptr; -#if !USE_MONO_AOT - AddDictionaryItem(nullptr, Instance, key, value, &exception); -#else - void* params[3]; - params[0] = Instance; - params[1] = key; - params[2] = value; - AddDictionaryItem->Invoke(Instance, params, &exception); -#endif - if (exception) - { - MException ex(exception); - ex.Log(LogType::Error, TEXT("")); - } - } - - MArray* GetKeys() const - { - CHECK_RETURN(Instance, nullptr); -#if !USE_MONO_AOT - return GetDictionaryKeys(nullptr, Instance, nullptr); -#else - void* params[1]; - params[0] = Instance; - return (MArray*)GetDictionaryKeys->Invoke(nullptr, params, nullptr); -#endif - } - - MObject* GetValue(MObject* key) const - { - CHECK_RETURN(Instance, nullptr); - MClass* klass = MCore::Object::GetClass(Instance); - MMethod* getItemMethod = klass->GetMethod("System.Collections.IDictionary.get_Item", 1); - CHECK_RETURN(getItemMethod, nullptr); - void* params[1]; - params[0] = key; - return getItemMethod->Invoke(Instance, params, nullptr); - } + MObject* GetValue(MObject* key) const; }; inline uint32 GetHash(const ManagedDictionary::KeyValueType& other) diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp index 5c0ad1676..67efbcb97 100644 --- a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp @@ -3,6 +3,8 @@ #include "MUtils.h" #include "MClass.h" #include "MCore.h" +#include "MMethod.h" +#include "MAssembly.h" #include "Engine/Core/Log.h" #include "Engine/Core/Types/DataContainer.h" #include "Engine/Core/Types/Version.h" @@ -19,6 +21,7 @@ #include "Engine/Core/Math/Ray.h" #include "Engine/Scripting/Scripting.h" #include "Engine/Scripting/ScriptingObject.h" +#include "Engine/Scripting/BinaryModule.h" #include "Engine/Scripting/Internal/StdTypesContainer.h" #include "Engine/Scripting/Internal/ManagedDictionary.h" #include "Engine/Utilities/StringConverter.h"