diff options
Diffstat (limited to 'modules/mono/mono_gd')
25 files changed, 603 insertions, 499 deletions
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 3298c5da4c..cf5ac33d20 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -130,9 +130,12 @@ void gd_mono_profiler_init() { } void gd_mono_debug_init() { - CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8(); + if (da_args.length()) { + OS::get_singleton()->set_environment("GODOT_MONO_DEBUGGER_AGENT", String()); + } + #ifdef TOOLS_ENABLED int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685); bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false); @@ -141,8 +144,9 @@ void gd_mono_debug_init() { if (Engine::get_singleton()->is_editor_hint() || ProjectSettings::get_singleton()->get_resource_path().empty() || Main::is_project_manager()) { - if (da_args.size() == 0) + if (da_args.size() == 0) { return; + } } if (da_args.length() == 0) { @@ -247,7 +251,6 @@ void GDMono::add_mono_shared_libs_dir_to_path() { } void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_dir) { - String bundled_assembly_rootdir = GodotSharpDirs::get_data_mono_lib_dir(); String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir(); @@ -310,7 +313,6 @@ void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_di } void GDMono::initialize() { - ERR_FAIL_NULL(Engine::get_singleton()); print_verbose("Mono: Initializing module..."); @@ -409,7 +411,6 @@ void GDMono::initialize() { } void GDMono::initialize_load_assemblies() { - #ifndef MONO_GLUE_ENABLED CRASH_NOW_MSG("Mono: This binary was built with 'mono_glue=no'; cannot load assemblies."); #endif @@ -422,22 +423,28 @@ void GDMono::initialize_load_assemblies() { #if defined(TOOLS_ENABLED) bool tool_assemblies_loaded = _load_tools_assemblies(); CRASH_COND_MSG(!tool_assemblies_loaded, "Mono: Failed to load '" TOOLS_ASM_NAME "' assemblies."); + + if (Main::is_project_manager()) { + return; + } #endif // Load the project's main assembly. This doesn't necessarily need to succeed. // The game may not be using .NET at all, or if the project does use .NET and // we're running in the editor, it may just happen to be it wasn't built yet. if (!_load_project_assembly()) { - if (OS::get_singleton()->is_stdout_verbose()) + if (OS::get_singleton()->is_stdout_verbose()) { print_error("Mono: Failed to load project assembly"); + } } } bool GDMono::_are_api_assemblies_out_of_sync() { bool out_of_sync = core_api_assembly.assembly && (core_api_assembly.out_of_sync || !GDMonoCache::cached_data.godot_api_cache_updated); #ifdef TOOLS_ENABLED - if (!out_of_sync) + if (!out_of_sync) { out_of_sync = editor_api_assembly.assembly && editor_api_assembly.out_of_sync; + } #endif return out_of_sync; } @@ -467,6 +474,7 @@ uint64_t get_editor_api_hash() { uint32_t get_bindings_version() { GD_UNREACHABLE(); } + uint32_t get_cs_glue_version() { GD_UNREACHABLE(); } @@ -508,25 +516,25 @@ void GDMono::_init_exception_policy() { } } -void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) { - +void GDMono::add_assembly(int32_t p_domain_id, GDMonoAssembly *p_assembly) { assemblies[p_domain_id][p_assembly->get_name()] = p_assembly; } GDMonoAssembly *GDMono::get_loaded_assembly(const String &p_name) { - - if (p_name == "mscorlib") - return get_corlib_assembly(); + if (p_name == "mscorlib" && corlib_assembly) { + return corlib_assembly; + } MonoDomain *domain = mono_domain_get(); - uint32_t domain_id = domain ? mono_domain_get_id(domain) : 0; + int32_t domain_id = domain ? mono_domain_get_id(domain) : 0; GDMonoAssembly **result = assemblies[domain_id].getptr(p_name); return result ? *result : nullptr; } bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) { - +#ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); +#endif MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); bool result = load_assembly(p_name, aname, r_assembly, p_refonly); @@ -537,27 +545,27 @@ bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bo } bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { +#ifdef DEBUG_ENABLED + CRASH_COND(!r_assembly); +#endif + + return load_assembly(p_name, p_aname, r_assembly, p_refonly, GDMonoAssembly::get_default_search_dirs()); +} +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly, const Vector<String> &p_search_dirs) { +#ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); +#endif print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); - MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssembly *assembly = mono_assembly_load_full(p_aname, nullptr, &status, p_refonly); + GDMonoAssembly *assembly = GDMonoAssembly::load(p_name, p_aname, p_refonly, p_search_dirs); - if (!assembly) + if (!assembly) { return false; + } - ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); - - uint32_t domain_id = mono_domain_get_id(mono_domain_get()); - - GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name); - - ERR_FAIL_COND_V(stored_assembly == nullptr, false); - ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false); - - *r_assembly = *stored_assembly; + *r_assembly = assembly; print_verbose("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path()); @@ -565,15 +573,15 @@ bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMo } bool GDMono::load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly, bool p_refonly) { - CRASH_COND(!r_assembly); print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); GDMonoAssembly *assembly = GDMonoAssembly::load_from(p_name, p_path, p_refonly); - if (!assembly) + if (!assembly) { return false; + } *r_assembly = assembly; @@ -593,16 +601,19 @@ ApiAssemblyInfo::Version ApiAssemblyInfo::Version::get_from_loaded_assembly(GDMo if (nativecalls_klass) { GDMonoField *api_hash_field = nativecalls_klass->get_field("godot_api_hash"); - if (api_hash_field) + if (api_hash_field) { api_assembly_version.godot_api_hash = GDMonoMarshal::unbox<uint64_t>(api_hash_field->get_value(nullptr)); + } GDMonoField *binds_ver_field = nativecalls_klass->get_field("bindings_version"); - if (binds_ver_field) + if (binds_ver_field) { api_assembly_version.bindings_version = GDMonoMarshal::unbox<uint32_t>(binds_ver_field->get_value(nullptr)); + } GDMonoField *cs_glue_ver_field = nativecalls_klass->get_field("cs_glue_version"); - if (cs_glue_ver_field) + if (cs_glue_ver_field) { api_assembly_version.cs_glue_version = GDMonoMarshal::unbox<uint32_t>(cs_glue_ver_field->get_value(nullptr)); + } } return api_assembly_version; @@ -613,21 +624,21 @@ String ApiAssemblyInfo::to_string(ApiAssemblyInfo::Type p_type) { } bool GDMono::_load_corlib_assembly() { - - if (corlib_assembly) + if (corlib_assembly) { return true; + } bool success = load_assembly("mscorlib", &corlib_assembly); - if (success) + if (success) { GDMonoCache::update_corlib_cache(); + } return success; } #ifdef TOOLS_ENABLED bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const String &p_config) { - String src_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file(p_config); String dst_dir = GodotSharpDirs::get_res_assemblies_base_dir().plus_file(p_config); @@ -648,12 +659,14 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String xml_file = assembly_name + ".xml"; - if (da->copy(src_dir.plus_file(xml_file), dst_dir.plus_file(xml_file)) != OK) + if (da->copy(src_dir.plus_file(xml_file), dst_dir.plus_file(xml_file)) != OK) { WARN_PRINT("Failed to copy '" + xml_file + "'."); + } String pdb_file = assembly_name + ".pdb"; - if (da->copy(src_dir.plus_file(pdb_file), dst_dir.plus_file(pdb_file)) != OK) + if (da->copy(src_dir.plus_file(pdb_file), dst_dir.plus_file(pdb_file)) != OK) { WARN_PRINT("Failed to copy '" + pdb_file + "'."); + } String assembly_file = assembly_name + ".dll"; if (da->copy(src_dir.plus_file(assembly_file), dst_dir.plus_file(assembly_file)) != OK) { @@ -668,13 +681,15 @@ static bool try_get_cached_api_hash_for(const String &p_api_assemblies_dir, bool String core_api_assembly_path = p_api_assemblies_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll"); String editor_api_assembly_path = p_api_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); - if (!FileAccess::exists(core_api_assembly_path) || !FileAccess::exists(editor_api_assembly_path)) + if (!FileAccess::exists(core_api_assembly_path) || !FileAccess::exists(editor_api_assembly_path)) { return false; + } String cached_api_hash_path = p_api_assemblies_dir.plus_file("api_hash_cache.cfg"); - if (!FileAccess::exists(cached_api_hash_path)) + if (!FileAccess::exists(cached_api_hash_path)) { return false; + } Ref<ConfigFile> cfg; cfg.instance(); @@ -698,7 +713,6 @@ static bool try_get_cached_api_hash_for(const String &p_api_assemblies_dir, bool } static void create_cached_api_hash_for(const String &p_api_assemblies_dir) { - String core_api_assembly_path = p_api_assemblies_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll"); String editor_api_assembly_path = p_api_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); String cached_api_hash_path = p_api_assemblies_dir.plus_file("api_hash_cache.cfg"); @@ -741,7 +755,6 @@ bool GDMono::_temp_domain_load_are_assemblies_out_of_sync(const String &p_config } String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const bool *p_core_api_out_of_sync, const bool *p_editor_api_out_of_sync) { - #define FAIL_REASON(m_out_of_sync, m_prebuilt_exists) \ ( \ (m_out_of_sync ? \ @@ -769,8 +782,9 @@ String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const // Note: Even if only one of the assemblies if missing or out of sync, we update both - if (!api_assemblies_out_of_sync && FileAccess::exists(core_assembly_path) && FileAccess::exists(editor_assembly_path)) + if (!api_assemblies_out_of_sync && FileAccess::exists(core_assembly_path) && FileAccess::exists(editor_assembly_path)) { return String(); // No update needed + } print_verbose("Updating '" + p_config + "' API assemblies"); @@ -798,9 +812,9 @@ String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const #endif bool GDMono::_load_core_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, const String &p_config, bool p_refonly) { - - if (r_loaded_api_assembly.assembly) + if (r_loaded_api_assembly.assembly) { return true; + } #ifdef TOOLS_ENABLED // For the editor and the editor player we want to load it from a specific path to make sure we can keep it up to date @@ -832,9 +846,9 @@ bool GDMono::_load_core_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, c #ifdef TOOLS_ENABLED bool GDMono::_load_editor_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, const String &p_config, bool p_refonly) { - - if (r_loaded_api_assembly.assembly) + if (r_loaded_api_assembly.assembly) { return true; + } // For the editor and the editor player we want to load it from a specific path to make sure we can keep it up to date @@ -864,30 +878,35 @@ bool GDMono::_load_editor_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, bool GDMono::_try_load_api_assemblies(LoadedApiAssembly &r_core_api_assembly, LoadedApiAssembly &r_editor_api_assembly, const String &p_config, bool p_refonly, CoreApiAssemblyLoadedCallback p_callback) { if (!_load_core_api_assembly(r_core_api_assembly, p_config, p_refonly)) { - if (OS::get_singleton()->is_stdout_verbose()) + if (OS::get_singleton()->is_stdout_verbose()) { print_error("Mono: Failed to load Core API assembly"); + } return false; } #ifdef TOOLS_ENABLED if (!_load_editor_api_assembly(r_editor_api_assembly, p_config, p_refonly)) { - if (OS::get_singleton()->is_stdout_verbose()) + if (OS::get_singleton()->is_stdout_verbose()) { print_error("Mono: Failed to load Editor API assembly"); + } return false; } - if (r_editor_api_assembly.out_of_sync) + if (r_editor_api_assembly.out_of_sync) { return false; + } #endif // Check if the core API assembly is out of sync only after trying to load the // editor API assembly. Otherwise, if both assemblies are out of sync, we would // only update the former as we won't know the latter also needs to be updated. - if (r_core_api_assembly.out_of_sync) + if (r_core_api_assembly.out_of_sync) { return false; + } - if (p_callback) + if (p_callback) { return p_callback(); + } return true; } @@ -895,8 +914,9 @@ bool GDMono::_try_load_api_assemblies(LoadedApiAssembly &r_core_api_assembly, Lo bool GDMono::_on_core_api_assembly_loaded() { GDMonoCache::update_godot_api_cache(); - if (!GDMonoCache::cached_data.godot_api_cache_updated) + if (!GDMonoCache::cached_data.godot_api_cache_updated) { return false; + } get_singleton()->_install_trace_listener(); @@ -909,7 +929,6 @@ bool GDMono::_try_load_api_assemblies_preset() { } void GDMono::_load_api_assemblies() { - bool api_assemblies_loaded = _try_load_api_assemblies_preset(); #if defined(TOOLS_ENABLED) && !defined(GD_MONO_SINGLE_APPDOMAIN) @@ -962,9 +981,9 @@ void GDMono::_load_api_assemblies() { #ifdef TOOLS_ENABLED bool GDMono::_load_tools_assemblies() { - - if (tools_assembly && tools_project_editor_assembly) + if (tools_assembly && tools_project_editor_assembly) { return true; + } bool success = load_assembly(TOOLS_ASM_NAME, &tools_assembly) && load_assembly(TOOLS_PROJECT_EDITOR_ASM_NAME, &tools_project_editor_assembly); @@ -974,9 +993,9 @@ bool GDMono::_load_tools_assemblies() { #endif bool GDMono::_load_project_assembly() { - - if (project_assembly) + if (project_assembly) { return true; + } String appname = ProjectSettings::get_singleton()->get("application/config/name"); String appname_safe = OS::get_singleton()->get_safe_dir_name(appname); @@ -994,7 +1013,6 @@ bool GDMono::_load_project_assembly() { } void GDMono::_install_trace_listener() { - #ifdef DEBUG_ENABLED // Install the trace listener now before the project assembly is loaded GDMonoClass *debug_utils = get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, "DebuggingUtils"); @@ -1011,7 +1029,6 @@ void GDMono::_install_trace_listener() { #ifndef GD_MONO_SINGLE_APPDOMAIN Error GDMono::_load_scripts_domain() { - ERR_FAIL_COND_V(scripts_domain != nullptr, ERR_BUG); print_verbose("Mono: Loading scripts domain..."); @@ -1026,13 +1043,13 @@ Error GDMono::_load_scripts_domain() { } Error GDMono::_unload_scripts_domain() { - ERR_FAIL_NULL_V(scripts_domain, ERR_BUG); print_verbose("Mono: Finalizing scripts domain..."); - if (mono_domain_get() != root_domain) + if (mono_domain_get() != root_domain) { mono_domain_set(root_domain, true); + } finalizing_scripts_domain = true; @@ -1079,7 +1096,6 @@ Error GDMono::_unload_scripts_domain() { #ifdef GD_MONO_HOT_RELOAD Error GDMono::reload_scripts_domain() { - ERR_FAIL_COND_V(!runtime_initialized, ERR_BUG); if (scripts_domain) { @@ -1116,7 +1132,6 @@ Error GDMono::reload_scripts_domain() { #ifndef GD_MONO_SINGLE_APPDOMAIN Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { - CRASH_COND(p_domain == nullptr); CRASH_COND(p_domain == GDMono::get_singleton()->get_scripts_domain()); // Should use _unload_scripts_domain() instead @@ -1124,8 +1139,9 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { print_verbose("Mono: Unloading domain '" + domain_name + "'..."); - if (mono_domain_get() == p_domain) + if (mono_domain_get() == p_domain) { mono_domain_set(root_domain, true); + } if (!mono_domain_finalize(p_domain, 2000)) { ERR_PRINT("Mono: Domain finalization timeout."); @@ -1149,13 +1165,13 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { #endif GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { - MonoImage *image = mono_class_get_image(p_raw_class); - if (image == corlib_assembly->get_image()) + if (image == corlib_assembly->get_image()) { return corlib_assembly->get_class(p_raw_class); + } - uint32_t domain_id = mono_domain_get_id(mono_domain_get()); + int32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; const String *k = nullptr; @@ -1163,9 +1179,9 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { GDMonoAssembly *assembly = domain_assemblies.get(*k); if (assembly->get_image() == image) { GDMonoClass *klass = assembly->get_class(p_raw_class); - - if (klass) + if (klass) { return klass; + } } } @@ -1173,27 +1189,27 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { } GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName &p_name) { - GDMonoClass *klass = corlib_assembly->get_class(p_namespace, p_name); - if (klass) + if (klass) { return klass; + } - uint32_t domain_id = mono_domain_get_id(mono_domain_get()); + int32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; const String *k = nullptr; while ((k = domain_assemblies.next(k))) { GDMonoAssembly *assembly = domain_assemblies.get(*k); klass = assembly->get_class(p_namespace, p_name); - if (klass) + if (klass) { return klass; + } } return nullptr; } -void GDMono::_domain_assemblies_cleanup(uint32_t p_domain_id) { - +void GDMono::_domain_assemblies_cleanup(int32_t p_domain_id) { HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id]; const String *k = nullptr; @@ -1205,15 +1221,15 @@ void GDMono::_domain_assemblies_cleanup(uint32_t p_domain_id) { } void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) { - // This method will be called by the runtime when a thrown exception is not handled. // It won't be called when we manually treat a thrown exception as unhandled. // We assume the exception was already printed before calling this hook. #ifdef DEBUG_ENABLED GDMonoUtils::debug_send_unhandled_exception_error((MonoException *)p_exc); - if (EngineDebugger::is_active()) + if (EngineDebugger::is_active()) { EngineDebugger::get_singleton()->poll_events(false); + } #endif exit(mono_environment_exitcode_get()); @@ -1222,7 +1238,6 @@ void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) { } GDMono::GDMono() { - singleton = this; gdmono_log = memnew(GDMonoLog); @@ -1249,7 +1264,6 @@ GDMono::GDMono() { } GDMono::~GDMono() { - if (is_runtime_initialized()) { #ifndef GD_MONO_SINGLE_APPDOMAIN if (scripts_domain) { @@ -1290,7 +1304,7 @@ GDMono::~GDMono() { // Leave the rest to 'mono_jit_cleanup' #endif - const uint32_t *k = nullptr; + const int32_t *k = nullptr; while ((k = assemblies.next(k))) { HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies.get(*k); @@ -1314,8 +1328,9 @@ GDMono::~GDMono() { gdmono::android::support::cleanup(); #endif - if (gdmono_log) + if (gdmono_log) { memdelete(gdmono_log); + } singleton = nullptr; } @@ -1323,79 +1338,76 @@ GDMono::~GDMono() { _GodotSharp *_GodotSharp::singleton = nullptr; void _GodotSharp::attach_thread() { - GDMonoUtils::attach_current_thread(); } void _GodotSharp::detach_thread() { - GDMonoUtils::detach_current_thread(); } int32_t _GodotSharp::get_domain_id() { - MonoDomain *domain = mono_domain_get(); - CRASH_COND(!domain); // User must check if runtime is initialized before calling this method + ERR_FAIL_NULL_V(domain, -1); return mono_domain_get_id(domain); } int32_t _GodotSharp::get_scripts_domain_id() { - + ERR_FAIL_NULL_V_MSG(GDMono::get_singleton(), + -1, "The Mono runtime is not initialized"); MonoDomain *domain = GDMono::get_singleton()->get_scripts_domain(); - CRASH_COND(!domain); // User must check if scripts domain is loaded before calling this method + ERR_FAIL_NULL_V(domain, -1); return mono_domain_get_id(domain); } bool _GodotSharp::is_scripts_domain_loaded() { - - return GDMono::get_singleton()->is_runtime_initialized() && GDMono::get_singleton()->get_scripts_domain() != nullptr; + return GDMono::get_singleton() != nullptr && + GDMono::get_singleton()->is_runtime_initialized() && + GDMono::get_singleton()->get_scripts_domain() != nullptr; } bool _GodotSharp::_is_domain_finalizing_for_unload(int32_t p_domain_id) { - return is_domain_finalizing_for_unload(p_domain_id); } -bool _GodotSharp::is_domain_finalizing_for_unload() { - - return is_domain_finalizing_for_unload(mono_domain_get()); -} - bool _GodotSharp::is_domain_finalizing_for_unload(int32_t p_domain_id) { - return is_domain_finalizing_for_unload(mono_domain_get_by_id(p_domain_id)); } bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) { + GDMono *gd_mono = GDMono::get_singleton(); - if (!p_domain) - return true; - if (p_domain == GDMono::get_singleton()->get_scripts_domain() && GDMono::get_singleton()->is_finalizing_scripts_domain()) + ERR_FAIL_COND_V_MSG(!gd_mono || !gd_mono->is_runtime_initialized(), + false, "The Mono runtime is not initialized"); + + ERR_FAIL_NULL_V(p_domain, true); + + if (p_domain == gd_mono->get_scripts_domain() && gd_mono->is_finalizing_scripts_domain()) { return true; + } + return mono_domain_is_unloading(p_domain); } bool _GodotSharp::is_runtime_shutting_down() { - return mono_runtime_is_shutting_down(); } bool _GodotSharp::is_runtime_initialized() { - - return GDMono::get_singleton()->is_runtime_initialized(); + return GDMono::get_singleton() != nullptr && GDMono::get_singleton()->is_runtime_initialized(); } void _GodotSharp::_reload_assemblies(bool p_soft_reload) { #ifdef GD_MONO_HOT_RELOAD + CRASH_COND(CSharpLanguage::get_singleton() == nullptr); // This method may be called more than once with `call_deferred`, so we need to check // again if reloading is needed to avoid reloading multiple times unnecessarily. - if (CSharpLanguage::get_singleton()->is_assembly_reloading_needed()) + if (CSharpLanguage::get_singleton()->is_assembly_reloading_needed()) { CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload); + } #endif } void _GodotSharp::_bind_methods() { - ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread); ClassDB::bind_method(D_METHOD("detach_thread"), &_GodotSharp::detach_thread); @@ -1410,11 +1422,9 @@ void _GodotSharp::_bind_methods() { } _GodotSharp::_GodotSharp() { - singleton = this; } _GodotSharp::~_GodotSharp() { - singleton = nullptr; } diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 4898833e8e..18f7418049 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -48,9 +48,9 @@ enum Type { }; struct Version { - uint64_t godot_api_hash; - uint32_t bindings_version; - uint32_t cs_glue_version; + uint64_t godot_api_hash = 0; + uint32_t bindings_version = 0; + uint32_t cs_glue_version = 0; bool operator==(const Version &p_other) const { return godot_api_hash == p_other.godot_api_hash && @@ -58,11 +58,7 @@ struct Version { cs_glue_version == p_other.cs_glue_version; } - Version() : - godot_api_hash(0), - bindings_version(0), - cs_glue_version(0) { - } + Version() {} Version(uint64_t p_godot_api_hash, uint32_t p_bindings_version, @@ -79,7 +75,6 @@ String to_string(Type p_type); } // namespace ApiAssemblyInfo class GDMono { - public: enum UnhandledExceptionPolicy { POLICY_TERMINATE_APP, @@ -87,13 +82,10 @@ public: }; struct LoadedApiAssembly { - GDMonoAssembly *assembly; - bool out_of_sync; + GDMonoAssembly *assembly = nullptr; + bool out_of_sync = false; - LoadedApiAssembly() : - assembly(nullptr), - out_of_sync(false) { - } + LoadedApiAssembly() {} }; private: @@ -105,7 +97,7 @@ private: MonoDomain *root_domain; MonoDomain *scripts_domain; - HashMap<uint32_t, HashMap<String, GDMonoAssembly *>> assemblies; + HashMap<int32_t, HashMap<String, GDMonoAssembly *>> assemblies; GDMonoAssembly *corlib_assembly; GDMonoAssembly *project_assembly; @@ -149,7 +141,7 @@ private: Error _unload_scripts_domain(); #endif - void _domain_assemblies_cleanup(uint32_t p_domain_id); + void _domain_assemblies_cleanup(int32_t p_domain_id); uint64_t api_core_hash; #ifdef TOOLS_ENABLED @@ -173,14 +165,16 @@ protected: public: #ifdef DEBUG_METHODS_ENABLED uint64_t get_api_core_hash() { - if (api_core_hash == 0) + if (api_core_hash == 0) { api_core_hash = ClassDB::get_api_hash(ClassDB::API_CORE); + } return api_core_hash; } #ifdef TOOLS_ENABLED uint64_t get_api_editor_hash() { - if (api_editor_hash == 0) + if (api_editor_hash == 0) { api_editor_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); + } return api_editor_hash; } #endif // TOOLS_ENABLED @@ -210,7 +204,7 @@ public: UnhandledExceptionPolicy get_unhandled_exception_policy() const { return unhandled_exception_policy; } // Do not use these, unless you know what you're doing - void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly); + void add_assembly(int32_t p_domain_id, GDMonoAssembly *p_assembly); GDMonoAssembly *get_loaded_assembly(const String &p_name); _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized && !mono_runtime_is_shutting_down() /* stays true after shutdown finished */; } @@ -241,6 +235,7 @@ public: bool load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly = false); bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false); + bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly, const Vector<String> &p_search_dirs); bool load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly, bool p_refonly = false); Error finalize_and_unload_domain(MonoDomain *p_domain); @@ -255,23 +250,22 @@ public: namespace gdmono { class ScopeDomain { - MonoDomain *prev_domain; public: ScopeDomain(MonoDomain *p_domain) { - MonoDomain *prev_domain = mono_domain_get(); + prev_domain = mono_domain_get(); if (prev_domain != p_domain) { - this->prev_domain = prev_domain; mono_domain_set(p_domain, false); } else { - this->prev_domain = nullptr; + prev_domain = nullptr; } } ~ScopeDomain() { - if (prev_domain) + if (prev_domain) { mono_domain_set(prev_domain, false); + } } }; @@ -284,8 +278,9 @@ public: } ~ScopeExitDomainUnload() { - if (domain) + if (domain) { GDMono::get_singleton()->finalize_and_unload_domain(domain); + } } }; @@ -306,9 +301,6 @@ class _GodotSharp : public Object { bool _is_domain_finalizing_for_unload(int32_t p_domain_id); - List<NodePath *> np_delete_queue; - List<RID *> rid_delete_queue; - void _reload_assemblies(bool p_soft_reload); protected: @@ -326,7 +318,6 @@ public: bool is_scripts_domain_loaded(); - bool is_domain_finalizing_for_unload(); bool is_domain_finalizing_for_unload(int32_t p_domain_id); bool is_domain_finalizing_for_unload(MonoDomain *p_domain); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 0f211eebc6..a170fd36e7 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -33,6 +33,7 @@ #include <mono/metadata/mono-debug.h> #include <mono/metadata/tokentype.h> +#include "core/io/file_access_pack.h" #include "core/list.h" #include "core/os/file_access.h" #include "core/os/os.h" @@ -45,7 +46,6 @@ Vector<String> GDMonoAssembly::search_dirs; void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config, const String &p_custom_bcl_dir) { - String framework_dir; if (!p_custom_bcl_dir.empty()) { @@ -99,8 +99,7 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin // - The 'load' hook is called after the assembly has been loaded. Its job is to add the // assembly to the list of loaded assemblies so that the 'search' hook can look it up. -void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) { - +void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, [[maybe_unused]] void *user_data) { String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly))); MonoImage *image = mono_assembly_get_image(assembly); @@ -109,8 +108,9 @@ void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) #ifdef GD_MONO_HOT_RELOAD const char *path = mono_image_get_filename(image); - if (FileAccess::exists(path)) + if (FileAccess::exists(path)) { gdassembly->modified_time = FileAccess::get_modified_time(path); + } #endif MonoDomain *domain = mono_domain_get(); @@ -133,30 +133,24 @@ MonoAssembly *GDMonoAssembly::assembly_refonly_preload_hook(MonoAssemblyName *an return GDMonoAssembly::_preload_hook(aname, assemblies_path, user_data, true); } -MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly) { - - (void)user_data; // UNUSED - +MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, [[maybe_unused]] void *user_data, bool refonly) { String name = String::utf8(mono_assembly_name_get_name(aname)); bool has_extension = name.ends_with(".dll") || name.ends_with(".exe"); GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); - if (loaded_asm) + if (loaded_asm) { return loaded_asm->get_assembly(); + } return nullptr; } -MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, void *user_data, bool refonly) { - - (void)user_data; // UNUSED - +MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, [[maybe_unused]] void *user_data, bool refonly) { String name = String::utf8(mono_assembly_name_get_name(aname)); - return _load_assembly_search(name, search_dirs, refonly); + return _load_assembly_search(name, aname, refonly, search_dirs); } -MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly) { - +MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) { MonoAssembly *res = nullptr; String path; @@ -168,23 +162,26 @@ MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const if (has_extension) { path = search_dir.plus_file(p_name); if (FileAccess::exists(path)) { - res = _real_load_assembly_from(path, p_refonly); - if (res != nullptr) + res = _real_load_assembly_from(path, p_refonly, p_aname); + if (res != nullptr) { return res; + } } } else { path = search_dir.plus_file(p_name + ".dll"); if (FileAccess::exists(path)) { - res = _real_load_assembly_from(path, p_refonly); - if (res != nullptr) + res = _real_load_assembly_from(path, p_refonly, p_aname); + if (res != nullptr) { return res; + } } path = search_dir.plus_file(p_name + ".exe"); if (FileAccess::exists(path)) { - res = _real_load_assembly_from(path, p_refonly); - if (res != nullptr) + res = _real_load_assembly_from(path, p_refonly, p_aname); + if (res != nullptr) { return res; + } } } } @@ -193,7 +190,6 @@ MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const } String GDMonoAssembly::find_assembly(const String &p_name) { - String path; bool has_extension = p_name.ends_with(".dll") || p_name.ends_with(".exe"); @@ -203,16 +199,19 @@ String GDMonoAssembly::find_assembly(const String &p_name) { if (has_extension) { path = search_dir.plus_file(p_name); - if (FileAccess::exists(path)) + if (FileAccess::exists(path)) { return path; + } } else { path = search_dir.plus_file(p_name + ".dll"); - if (FileAccess::exists(path)) + if (FileAccess::exists(path)) { return path; + } path = search_dir.plus_file(p_name + ".exe"); - if (FileAccess::exists(path)) + if (FileAccess::exists(path)) { return path; + } } } @@ -220,7 +219,6 @@ String GDMonoAssembly::find_assembly(const String &p_name) { } void GDMonoAssembly::initialize() { - fill_search_dirs(search_dirs); mono_install_assembly_search_hook(&assembly_search_hook, nullptr); @@ -230,8 +228,7 @@ void GDMonoAssembly::initialize() { mono_install_assembly_load_hook(&assembly_load_hook, nullptr); } -MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, bool p_refonly) { - +MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, bool p_refonly, MonoAssemblyName *p_aname) { Vector<uint8_t> data = FileAccess::get_file_as_array(p_path); ERR_FAIL_COND_V_MSG(data.empty(), nullptr, "Could read the assembly in the specified location"); @@ -255,7 +252,33 @@ MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, boo true, &status, p_refonly, image_filename.utf8()); - ERR_FAIL_COND_V_MSG(status != MONO_IMAGE_OK || !image, nullptr, "Failed to open assembly image from the loaded data"); + ERR_FAIL_COND_V_MSG(status != MONO_IMAGE_OK || !image, nullptr, "Failed to open assembly image from memory: '" + p_path + "'."); + + if (p_aname != nullptr) { + // Check assembly version + const MonoTableInfo *table = mono_image_get_table_info(image, MONO_TABLE_ASSEMBLY); + + ERR_FAIL_NULL_V(table, nullptr); + + if (mono_table_info_get_rows(table)) { + uint32_t cols[MONO_ASSEMBLY_SIZE]; + mono_metadata_decode_row(table, 0, cols, MONO_ASSEMBLY_SIZE); + + // Not sure about .NET's policy. We will only ensure major and minor are equal, and ignore build and revision. + uint16_t major = cols[MONO_ASSEMBLY_MAJOR_VERSION]; + uint16_t minor = cols[MONO_ASSEMBLY_MINOR_VERSION]; + + uint16_t required_minor; + uint16_t required_major = mono_assembly_name_get_version(p_aname, &required_minor, nullptr, nullptr); + + if (required_major != 0) { + if (major != required_major && minor != required_minor) { + mono_image_close(image); + return nullptr; + } + } + } + } #ifdef DEBUG_ENABLED Vector<uint8_t> pdb_data; @@ -264,8 +287,9 @@ MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, boo if (!FileAccess::exists(pdb_path)) { pdb_path = p_path.get_basename() + ".pdb"; // without .dll - if (!FileAccess::exists(pdb_path)) + if (!FileAccess::exists(pdb_path)) { goto no_pdb; + } } pdb_data = FileAccess::get_file_as_array(pdb_path); @@ -292,8 +316,9 @@ no_pdb: String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly))); bool has_extension = name.ends_with(".dll") || name.ends_with(".exe"); GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); - if (!loaded_asm) + if (!loaded_asm) { assembly_load_hook(assembly, nullptr); + } } // Decrement refcount which was previously incremented by mono_image_open_from_data_with_name @@ -303,7 +328,6 @@ no_pdb: } void GDMonoAssembly::unload() { - ERR_FAIL_NULL(image); // Should not be called if already unloaded for (Map<MonoClass *, GDMonoClass *>::Element *E = cached_raw.front(); E; E = E->next()) { @@ -322,20 +346,21 @@ String GDMonoAssembly::get_path() const { } GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const StringName &p_name) { - ERR_FAIL_NULL_V(image, nullptr); ClassKey key(p_namespace, p_name); GDMonoClass **match = cached_classes.getptr(key); - if (match) + if (match) { return *match; + } MonoClass *mono_class = mono_class_from_name(image, String(p_namespace).utf8(), String(p_name).utf8()); - if (!mono_class) + if (!mono_class) { return nullptr; + } GDMonoClass *wrapped_class = memnew(GDMonoClass(p_namespace, p_name, mono_class, this)); @@ -346,13 +371,13 @@ GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const Stri } GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) { - ERR_FAIL_NULL_V(image, nullptr); Map<MonoClass *, GDMonoClass *>::Element *match = cached_raw.find(p_mono_class); - if (match) + if (match) { return match->value(); + } StringName namespace_name = mono_class_get_namespace(p_mono_class); StringName class_name = mono_class_get_name(p_mono_class); @@ -366,14 +391,14 @@ GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) { } GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) { - GDMonoClass *match = nullptr; if (gdobject_class_cache_updated) { Map<StringName, GDMonoClass *>::Element *result = gdobject_class_cache.find(p_class); - if (result) + if (result) { match = result->get(); + } } else { List<GDMonoClass *> nested_classes; @@ -382,18 +407,21 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) for (int i = 1; i < rows; i++) { MonoClass *mono_class = mono_class_get(image, (i + 1) | MONO_TOKEN_TYPE_DEF); - if (!mono_class_is_assignable_from(CACHED_CLASS_RAW(GodotObject), mono_class)) + if (!mono_class_is_assignable_from(CACHED_CLASS_RAW(GodotObject), mono_class)) { continue; + } GDMonoClass *current = get_class(mono_class); - if (!current) + if (!current) { continue; + } nested_classes.push_back(current); - if (!match && current->get_name() == p_class) + if (!match && current->get_name() == p_class) { match = current; + } while (!nested_classes.empty()) { GDMonoClass *current_nested = nested_classes.front()->get(); @@ -404,8 +432,9 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) while (true) { MonoClass *raw_nested = mono_class_get_nested_types(current_nested->get_mono_ptr(), &iter); - if (!raw_nested) + if (!raw_nested) { break; + } GDMonoClass *nested_class = get_class(raw_nested); @@ -425,10 +454,30 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) return match; } -GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { +GDMonoAssembly *GDMonoAssembly::load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) { + if (GDMono::get_singleton()->get_corlib_assembly() && (p_name == "mscorlib" || p_name == "mscorlib.dll")) { + return GDMono::get_singleton()->get_corlib_assembly(); + } + + // We need to manually call the search hook in this case, as it won't be called in the next step + MonoAssembly *assembly = mono_assembly_invoke_search_hook(p_aname); + + if (!assembly) { + assembly = _load_assembly_search(p_name, p_aname, p_refonly, p_search_dirs); + ERR_FAIL_NULL_V(assembly, nullptr); + } + + GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); + ERR_FAIL_NULL_V_MSG(loaded_asm, nullptr, "Loaded assembly missing from table. Did we not receive the load hook?"); + ERR_FAIL_COND_V(loaded_asm->get_assembly() != assembly, nullptr); + + return loaded_asm; +} - if (p_name == "mscorlib" || p_name == "mscorlib.dll") +GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { + if (p_name == "mscorlib" || p_name == "mscorlib.dll") { return GDMono::get_singleton()->get_corlib_assembly(); + } // We need to manually call the search hook in this case, as it won't be called in the next step MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); @@ -447,18 +496,8 @@ GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_ return loaded_asm; } -GDMonoAssembly::GDMonoAssembly(const String &p_name, MonoImage *p_image, MonoAssembly *p_assembly) : - name(p_name), - image(p_image), - assembly(p_assembly), -#ifdef GD_MONO_HOT_RELOAD - modified_time(0), -#endif - gdobject_class_cache_updated(false) { -} - GDMonoAssembly::~GDMonoAssembly() { - - if (image) + if (image) { unload(); + } } diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 43c8225b74..63899dc9be 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -40,7 +40,6 @@ #include "gd_mono_utils.h" class GDMonoAssembly { - struct ClassKey { struct Hasher { static _FORCE_INLINE_ uint32_t hash(const ClassKey &p_key) { @@ -73,10 +72,10 @@ class GDMonoAssembly { MonoAssembly *assembly; #ifdef GD_MONO_HOT_RELOAD - uint64_t modified_time; + uint64_t modified_time = 0; #endif - bool gdobject_class_cache_updated; + bool gdobject_class_cache_updated = false; Map<StringName, GDMonoClass *> gdobject_class_cache; HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes; @@ -93,8 +92,8 @@ class GDMonoAssembly { static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly); static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly); - static MonoAssembly *_real_load_assembly_from(const String &p_path, bool p_refonly); - static MonoAssembly *_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly); + static MonoAssembly *_real_load_assembly_from(const String &p_path, bool p_refonly, MonoAssemblyName *p_aname = nullptr); + static MonoAssembly *_load_assembly_search(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs); friend class GDMono; static void initialize(); @@ -120,10 +119,16 @@ public: static String find_assembly(const String &p_name); static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String(), const String &p_custom_bcl_dir = String()); + static const Vector<String> &get_default_search_dirs() { return search_dirs; } + static GDMonoAssembly *load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs); static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly); - GDMonoAssembly(const String &p_name, MonoImage *p_image, MonoAssembly *p_assembly); + GDMonoAssembly(const String &p_name, MonoImage *p_image, MonoAssembly *p_assembly) : + name(p_name), + image(p_image), + assembly(p_assembly) { + } ~GDMonoAssembly(); }; diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index 5ddf18d544..29aef6e609 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -65,7 +65,6 @@ CachedData cached_data; #define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_METHOD_THUNK_AND_CHECK_IMPL(cached_data.methodthunk_##m_class##_##m_method, m_val) void CachedData::clear_corlib_cache() { - corlib_cache_updated = false; class_MonoObject = nullptr; @@ -98,7 +97,6 @@ void CachedData::clear_corlib_cache() { } void CachedData::clear_godot_api_cache() { - godot_api_cache_updated = false; rawclass_Dictionary = nullptr; @@ -193,7 +191,6 @@ void CachedData::clear_godot_api_cache() { #define GODOT_API_NS_CLASS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class)) void update_corlib_cache() { - CACHE_CLASS_AND_CHECK(MonoObject, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_object_class())); CACHE_CLASS_AND_CHECK(bool, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_boolean_class())); CACHE_CLASS_AND_CHECK(int8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_sbyte_class())); @@ -220,7 +217,7 @@ void update_corlib_cache() { CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true)); #endif - CACHE_METHOD_THUNK_AND_CHECK(Delegate, Equals, GDMono::get_singleton()->get_corlib_assembly()->get_class("System", "Delegate")->get_method_with_desc("System.Delegate:Equals(object)", 1)); + CACHE_METHOD_THUNK_AND_CHECK(Delegate, Equals, GDMono::get_singleton()->get_corlib_assembly()->get_class("System", "Delegate")->get_method_with_desc("System.Delegate:Equals(object)", true)); CACHE_CLASS_AND_CHECK(KeyNotFoundException, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections.Generic", "KeyNotFoundException")); @@ -228,7 +225,6 @@ void update_corlib_cache() { } void update_godot_api_cache() { - CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2)); CACHE_CLASS_AND_CHECK(Vector2i, GODOT_API_CLASS(Vector2i)); CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2)); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 3cf2bd6ce5..a7bbc763a7 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -37,7 +37,6 @@ namespace GDMonoCache { struct CachedData { - // ----------------------------------------------- // corlib classes diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 2c65f7e3a0..6575cbc1c8 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -79,19 +79,34 @@ bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const { return mono_class_is_assignable_from(mono_class, p_from->mono_class); } -GDMonoClass *GDMonoClass::get_parent_class() { +StringName GDMonoClass::get_namespace() const { + GDMonoClass *nesting_class = get_nesting_class(); + if (!nesting_class) { + return namespace_name; + } + return nesting_class->get_namespace(); +} + +String GDMonoClass::get_name_for_lookup() const { + GDMonoClass *nesting_class = get_nesting_class(); + if (!nesting_class) { + return class_name; + } + return nesting_class->get_name_for_lookup() + "/" + class_name; +} + +GDMonoClass *GDMonoClass::get_parent_class() const { MonoClass *parent_mono_class = mono_class_get_parent(mono_class); return parent_mono_class ? GDMono::get_singleton()->get_class(parent_mono_class) : nullptr; } -GDMonoClass *GDMonoClass::get_nesting_class() { +GDMonoClass *GDMonoClass::get_nesting_class() const { MonoClass *nesting_type = mono_class_get_nesting_type(mono_class); return nesting_type ? GDMono::get_singleton()->get_class(nesting_type) : nullptr; } #ifdef TOOLS_ENABLED Vector<MonoClassField *> GDMonoClass::get_enum_fields() { - bool class_is_enum = mono_class_is_enum(mono_class); ERR_FAIL_COND_V(!class_is_enum, Vector<MonoClassField *>()); @@ -114,37 +129,38 @@ Vector<MonoClassField *> GDMonoClass::get_enum_fields() { #endif bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) { - #ifdef DEBUG_ENABLED ERR_FAIL_NULL_V(p_attr_class, false); #endif - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return false; + } return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); } MonoObject *GDMonoClass::get_attribute(GDMonoClass *p_attr_class) { - #ifdef DEBUG_ENABLED ERR_FAIL_NULL_V(p_attr_class, nullptr); #endif - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return nullptr; + } return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoClass::fetch_attributes() { - ERR_FAIL_COND(attributes != nullptr); attributes = mono_custom_attrs_from_class(get_mono_ptr()); @@ -152,11 +168,11 @@ void GDMonoClass::fetch_attributes() { } void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base) { - CRASH_COND(!CACHED_CLASS(GodotObject)->is_assignable_from(this)); - if (methods_fetched) + if (methods_fetched) { return; + } void *iter = nullptr; MonoMethod *raw_method = nullptr; @@ -168,7 +184,6 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base ERR_CONTINUE(!method); if (method->get_name() != name) { - #ifdef DEBUG_ENABLED String fullname = method->get_ret_type_full_name() + " " + name + "(" + method->get_signature_desc(true) + ")"; WARN_PRINT("Method '" + fullname + "' is hidden by Godot API method. Should be '" + @@ -182,7 +197,6 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base // This allows us to warn the user here if he is using snake_case by mistake. if (p_native_base != this) { - GDMonoClass *native_top = p_native_base; while (native_top) { GDMonoMethod *m = native_top->get_method(name, method->get_parameters_count()); @@ -195,8 +209,9 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base break; } - if (native_top == CACHED_CLASS(GodotObject)) + if (native_top == CACHED_CLASS(GodotObject)) { break; + } native_top = native_top->get_parent_class(); } @@ -205,8 +220,9 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base uint32_t flags = mono_method_get_flags(method->mono_method, nullptr); - if (!(flags & MONO_METHOD_ATTR_VIRTUAL)) + if (!(flags & MONO_METHOD_ATTR_VIRTUAL)) { continue; + } // Virtual method of Godot Object derived type, let's try to find GodotMethod attribute @@ -228,15 +244,17 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base #endif MethodKey key = MethodKey(godot_method_name, method->get_parameters_count()); GDMonoMethod **existing_method = methods.getptr(key); - if (existing_method) + if (existing_method) { memdelete(*existing_method); // Must delete old one + } methods.set(key, method); break; } - if (top == CACHED_CLASS(GodotObject)) + if (top == CACHED_CLASS(GodotObject)) { break; + } top = top->get_parent_class(); } @@ -246,46 +264,44 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base } GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) { - ERR_FAIL_COND_V(!methods_fetched, nullptr); const MethodKey *k = nullptr; while ((k = methods.next(k))) { - if (k->name == p_name) + if (k->name == p_name) { return methods.get(*k); + } } return nullptr; } bool GDMonoClass::has_fetched_method_unknown_params(const StringName &p_name) { - return get_fetched_method_unknown_params(p_name) != nullptr; } bool GDMonoClass::implements_interface(GDMonoClass *p_interface) { - return mono_class_implements_interface(mono_class, p_interface->get_mono_ptr()); } bool GDMonoClass::has_public_parameterless_ctor() { - GDMonoMethod *ctor = get_method(".ctor", 0); return ctor && ctor->get_visibility() == IMonoClassMember::PUBLIC; } GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) { - MethodKey key = MethodKey(p_name, p_params_count); GDMonoMethod **match = methods.getptr(key); - if (match) + if (match) { return *match; + } - if (methods_fetched) + if (methods_fetched) { return nullptr; + } MonoMethod *raw_method = mono_class_get_method_from_name(mono_class, String(p_name).utf8().get_data(), p_params_count); @@ -300,7 +316,6 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_cou } GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) { - MonoMethodSignature *sig = mono_method_signature(p_raw_method); int params_count = mono_signature_get_param_count(sig); @@ -310,22 +325,21 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) { } GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name) { - MonoMethodSignature *sig = mono_method_signature(p_raw_method); int params_count = mono_signature_get_param_count(sig); return get_method(p_raw_method, p_name, params_count); } GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count) { - ERR_FAIL_NULL_V(p_raw_method, nullptr); MethodKey key = MethodKey(p_name, p_params_count); GDMonoMethod **match = methods.getptr(key); - if (match) + if (match) { return *match; + } GDMonoMethod *method = memnew(GDMonoMethod(p_name, p_raw_method)); methods.set(key, method); @@ -334,13 +348,13 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName } GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, bool p_include_namespace) { - MonoMethodDesc *desc = mono_method_desc_new(p_description.utf8().get_data(), p_include_namespace); MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class); mono_method_desc_free(desc); - if (!method) + if (!method) { return nullptr; + } ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, nullptr); @@ -348,14 +362,15 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo } GDMonoField *GDMonoClass::get_field(const StringName &p_name) { - Map<StringName, GDMonoField *>::Element *result = fields.find(p_name); - if (result) + if (result) { return result->value(); + } - if (fields_fetched) + if (fields_fetched) { return nullptr; + } MonoClassField *raw_field = mono_class_get_field_from_name(mono_class, String(p_name).utf8().get_data()); @@ -370,9 +385,9 @@ GDMonoField *GDMonoClass::get_field(const StringName &p_name) { } const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { - - if (fields_fetched) + if (fields_fetched) { return fields_list; + } void *iter = nullptr; MonoClassField *raw_field = nullptr; @@ -396,14 +411,15 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { } GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) { - Map<StringName, GDMonoProperty *>::Element *result = properties.find(p_name); - if (result) + if (result) { return result->value(); + } - if (properties_fetched) + if (properties_fetched) { return nullptr; + } MonoProperty *raw_property = mono_class_get_property_from_name(mono_class, String(p_name).utf8().get_data()); @@ -418,9 +434,9 @@ GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) { } const Vector<GDMonoProperty *> &GDMonoClass::get_all_properties() { - - if (properties_fetched) + if (properties_fetched) { return properties_list; + } void *iter = nullptr; MonoProperty *raw_property = nullptr; @@ -444,8 +460,9 @@ const Vector<GDMonoProperty *> &GDMonoClass::get_all_properties() { } const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() { - if (delegates_fetched) + if (delegates_fetched) { return delegates_list; + } void *iter = nullptr; MonoClass *raw_class = nullptr; @@ -471,7 +488,6 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() { } const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() { - if (!method_list_fetched) { void *iter = nullptr; MonoMethod *raw_method = nullptr; @@ -486,7 +502,6 @@ const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() { } GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) { - namespace_name = p_namespace; class_name = p_name; mono_class = p_class; @@ -503,7 +518,6 @@ GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name } GDMonoClass::~GDMonoClass() { - if (attributes) { mono_custom_attrs_free(attributes); } diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index 9237aae057..44b146b87c 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -113,14 +113,15 @@ public: bool is_assignable_from(GDMonoClass *p_from) const; - _FORCE_INLINE_ StringName get_namespace() const { return namespace_name; } + StringName get_namespace() const; _FORCE_INLINE_ StringName get_name() const { return class_name; } + String get_name_for_lookup() const; _FORCE_INLINE_ MonoClass *get_mono_ptr() const { return mono_class; } _FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; } - GDMonoClass *get_parent_class(); - GDMonoClass *get_nesting_class(); + GDMonoClass *get_parent_class() const; + GDMonoClass *get_nesting_class() const; #ifdef TOOLS_ENABLED Vector<MonoClassField *> get_enum_fields(); diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index e76cb84d43..563c45e71f 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -501,7 +501,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ case Variant::PACKED_COLOR_ARRAY: { SET_FROM_ARRAY(PackedColorArray); } break; - default: break; + default: + break; } } break; @@ -596,11 +597,13 @@ String GDMonoField::get_string_value(MonoObject *p_object) { bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) { ERR_FAIL_NULL_V(p_attr_class, false); - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return false; + } return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); } @@ -608,11 +611,13 @@ bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) { MonoObject *GDMonoField::get_attribute(GDMonoClass *p_attr_class) { ERR_FAIL_NULL_V(p_attr_class, nullptr); - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return nullptr; + } return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index 61f2c8f071..5b40b439f9 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -36,7 +36,6 @@ #include "i_mono_class_member.h" class GDMonoField : public IMonoClassMember { - GDMonoClass *owner; MonoClassField *mono_field; diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index 1898785699..fe1c2d28dd 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -45,7 +45,6 @@ namespace GDMonoInternals { void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { - // This method should not fail CRASH_COND(!unmanaged); @@ -115,7 +114,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { } void unhandled_exception(MonoException *p_exc) { - mono_unhandled_exception((MonoObject *)p_exc); // prints the exception as well + mono_print_unhandled_exception((MonoObject *)p_exc); if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) { // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders @@ -123,9 +122,10 @@ void unhandled_exception(MonoException *p_exc) { GD_UNREACHABLE(); } else { #ifdef DEBUG_ENABLED - GDMonoUtils::debug_send_unhandled_exception_error((MonoException *)p_exc); - if (EngineDebugger::is_active()) + GDMonoUtils::debug_send_unhandled_exception_error(p_exc); + if (EngineDebugger::is_active()) { EngineDebugger::get_singleton()->poll_events(false); + } #endif } } diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index ca16c2b76a..c5a988b8c3 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -51,13 +51,13 @@ GDMonoLog *GDMonoLog::singleton = nullptr; #ifdef GD_MONO_LOG_ENABLED static int get_log_level_id(const char *p_log_level) { - const char *valid_log_levels[] = { "error", "critical", "warning", "message", "info", "debug", nullptr }; int i = 0; while (valid_log_levels[i]) { - if (!strcmp(valid_log_levels[i], p_log_level)) + if (!strcmp(valid_log_levels[i], p_log_level)) { return i; + } i++; } @@ -65,7 +65,6 @@ static int get_log_level_id(const char *p_log_level) { } void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *) { - FileAccess *f = GDMonoLog::get_singleton()->log_file; if (GDMonoLog::get_singleton()->log_level_id >= get_log_level_id(log_level)) { @@ -94,7 +93,6 @@ void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, } bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) { - if (!DirAccess::exists(p_logs_dir)) { DirAccessRef diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); ERR_FAIL_COND_V(!diraccess, false); @@ -106,7 +104,6 @@ bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) { } void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) { - static const uint64_t MAX_SECS = 5 * 86400; // 5 days DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -119,10 +116,12 @@ void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) { String current; while ((current = da->get_next()).length()) { - if (da->current_is_dir()) + if (da->current_is_dir()) { continue; - if (!current.ends_with(".txt")) + } + if (!current.ends_with(".txt")) { continue; + } uint64_t modified_time = FileAccess::get_modified_time(da->get_current_dir().plus_file(current)); @@ -135,7 +134,6 @@ void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) { } void GDMonoLog::initialize() { - CharString log_level = OS::get_singleton()->get_environment("GODOT_MONO_LOG_LEVEL").utf8(); if (log_level.length() != 0 && get_log_level_id(log_level.get_data()) == -1) { @@ -175,7 +173,7 @@ void GDMonoLog::initialize() { log_level_id = get_log_level_id(log_level.get_data()); if (log_file) { - OS::get_singleton()->print("Mono: Logfile is: %s\n", log_file_path.utf8().get_data()); + OS::get_singleton()->print("Mono: Log file is: '%s'\n", log_file_path.utf8().get_data()); mono_trace_set_log_handler(mono_log_callback, this); } else { OS::get_singleton()->printerr("Mono: No log file, using default log handler\n"); @@ -183,14 +181,12 @@ void GDMonoLog::initialize() { } GDMonoLog::GDMonoLog() { - singleton = this; log_level_id = -1; } GDMonoLog::~GDMonoLog() { - singleton = nullptr; if (log_file) { @@ -207,12 +203,10 @@ void GDMonoLog::initialize() { } GDMonoLog::GDMonoLog() { - singleton = this; } GDMonoLog::~GDMonoLog() { - singleton = nullptr; } diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h index 1fc21f7df5..3a52316060 100644 --- a/modules/mono/mono_gd/gd_mono_log.h +++ b/modules/mono/mono_gd/gd_mono_log.h @@ -45,7 +45,6 @@ #endif class GDMonoLog { - #ifdef GD_MONO_LOG_ENABLED int log_level_id; diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 91ee07388b..6d7d5f76cd 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -72,92 +72,119 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ case MONO_TYPE_VALUETYPE: { GDMonoClass *vtclass = p_type.type_class; - if (vtclass == CACHED_CLASS(Vector2)) + if (vtclass == CACHED_CLASS(Vector2)) { return Variant::VECTOR2; + } - if (vtclass == CACHED_CLASS(Vector2i)) + if (vtclass == CACHED_CLASS(Vector2i)) { return Variant::VECTOR2I; + } - if (vtclass == CACHED_CLASS(Rect2)) + if (vtclass == CACHED_CLASS(Rect2)) { return Variant::RECT2; + } - if (vtclass == CACHED_CLASS(Rect2i)) + if (vtclass == CACHED_CLASS(Rect2i)) { return Variant::RECT2I; + } - if (vtclass == CACHED_CLASS(Transform2D)) + if (vtclass == CACHED_CLASS(Transform2D)) { return Variant::TRANSFORM2D; + } - if (vtclass == CACHED_CLASS(Vector3)) + if (vtclass == CACHED_CLASS(Vector3)) { return Variant::VECTOR3; + } - if (vtclass == CACHED_CLASS(Vector3i)) + if (vtclass == CACHED_CLASS(Vector3i)) { return Variant::VECTOR3I; + } - if (vtclass == CACHED_CLASS(Basis)) + if (vtclass == CACHED_CLASS(Basis)) { return Variant::BASIS; + } - if (vtclass == CACHED_CLASS(Quat)) + if (vtclass == CACHED_CLASS(Quat)) { return Variant::QUAT; + } - if (vtclass == CACHED_CLASS(Transform)) + if (vtclass == CACHED_CLASS(Transform)) { return Variant::TRANSFORM; + } - if (vtclass == CACHED_CLASS(AABB)) + if (vtclass == CACHED_CLASS(AABB)) { return Variant::AABB; + } - if (vtclass == CACHED_CLASS(Color)) + if (vtclass == CACHED_CLASS(Color)) { return Variant::COLOR; + } - if (vtclass == CACHED_CLASS(Plane)) + if (vtclass == CACHED_CLASS(Plane)) { return Variant::PLANE; + } - if (vtclass == CACHED_CLASS(Callable)) + if (vtclass == CACHED_CLASS(Callable)) { return Variant::CALLABLE; + } - if (vtclass == CACHED_CLASS(SignalInfo)) + if (vtclass == CACHED_CLASS(SignalInfo)) { return Variant::SIGNAL; + } - if (mono_class_is_enum(vtclass->get_mono_ptr())) + if (mono_class_is_enum(vtclass->get_mono_ptr())) { return Variant::INT; + } } break; case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: { MonoArrayType *array_type = mono_type_get_array_type(p_type.type_class->get_mono_type()); - if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) + if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) { return Variant::ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) + if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) { return Variant::PACKED_BYTE_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) + if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) { return Variant::PACKED_INT32_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) + if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) { return Variant::PACKED_INT64_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(float)) + if (array_type->eklass == CACHED_CLASS_RAW(float)) { return Variant::PACKED_FLOAT32_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(double)) + if (array_type->eklass == CACHED_CLASS_RAW(double)) { return Variant::PACKED_FLOAT64_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(String)) + if (array_type->eklass == CACHED_CLASS_RAW(String)) { return Variant::PACKED_STRING_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) + if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) { return Variant::PACKED_VECTOR2_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) + if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) { return Variant::PACKED_VECTOR3_ARRAY; + } - if (array_type->eklass == CACHED_CLASS_RAW(Color)) + if (array_type->eklass == CACHED_CLASS_RAW(Color)) { return Variant::PACKED_COLOR_ARRAY; + } GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); - if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) { return Variant::ARRAY; + } } break; case MONO_TYPE_CLASS: { @@ -201,8 +228,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ } break; case MONO_TYPE_OBJECT: { - if (r_nil_is_variant) + if (r_nil_is_variant) { *r_nil_is_variant = true; + } return Variant::NIL; } break; @@ -244,8 +272,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ } break; } - if (r_nil_is_variant) + if (r_nil_is_variant) { *r_nil_is_variant = false; + } // Unknown return Variant::NIL; @@ -282,31 +311,6 @@ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_ return false; } -bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, ManagedType &r_key_type, ManagedType &r_value_type) { - switch (p_dictionary_type.type_encoding) { - case MONO_TYPE_GENERICINST: { - MonoReflectionType *dict_reftype = mono_type_get_object(mono_domain_get(), p_dictionary_type.type_class->get_mono_type()); - - if (GDMonoUtils::Marshal::type_is_generic_dictionary(dict_reftype) || - GDMonoUtils::Marshal::type_is_system_generic_dictionary(dict_reftype) || - GDMonoUtils::Marshal::type_is_generic_idictionary(dict_reftype)) { - MonoReflectionType *key_reftype; - MonoReflectionType *value_reftype; - - GDMonoUtils::Marshal::dictionary_get_key_value_types(dict_reftype, &key_reftype, &value_reftype); - - r_key_type = ManagedType::from_reftype(key_reftype); - r_value_type = ManagedType::from_reftype(value_reftype); - return true; - } - } break; - default: { - } break; - } - - return false; -} - String mono_to_utf8_string(MonoString *p_mono_string) { MonoError error; char *utf8 = mono_string_to_utf8_checked(p_mono_string, &error); @@ -328,8 +332,9 @@ String mono_to_utf16_string(MonoString *p_mono_string) { int len = mono_string_length(p_mono_string); String ret; - if (len == 0) + if (len == 0) { return ret; + } ret.resize(len + 1); ret.set(len, 0); @@ -409,8 +414,9 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty } case MONO_TYPE_STRING: { - if (p_var->get_type() == Variant::NIL) + if (p_var->get_type() == Variant::NIL) { return nullptr; // Otherwise, Variant -> String would return the string "Null" + } return (MonoObject *)mono_string_from_godot(p_var->operator String()); } break; @@ -547,39 +553,50 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty case MONO_TYPE_SZARRAY: { MonoArrayType *array_type = mono_type_get_array_type(p_type.type_class->get_mono_type()); - if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) + if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) { return (MonoObject *)Array_to_mono_array(p_var->operator Array()); + } - if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) + if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) { return (MonoObject *)PackedByteArray_to_mono_array(p_var->operator PackedByteArray()); + } - if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) + if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) { return (MonoObject *)PackedInt32Array_to_mono_array(p_var->operator PackedInt32Array()); + } - if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) + if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) { return (MonoObject *)PackedInt64Array_to_mono_array(p_var->operator PackedInt64Array()); + } - if (array_type->eklass == CACHED_CLASS_RAW(float)) + if (array_type->eklass == CACHED_CLASS_RAW(float)) { return (MonoObject *)PackedFloat32Array_to_mono_array(p_var->operator PackedFloat32Array()); + } - if (array_type->eklass == CACHED_CLASS_RAW(double)) + if (array_type->eklass == CACHED_CLASS_RAW(double)) { return (MonoObject *)PackedFloat64Array_to_mono_array(p_var->operator PackedFloat64Array()); + } - if (array_type->eklass == CACHED_CLASS_RAW(String)) + if (array_type->eklass == CACHED_CLASS_RAW(String)) { return (MonoObject *)PackedStringArray_to_mono_array(p_var->operator PackedStringArray()); + } - if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) + if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) { return (MonoObject *)PackedVector2Array_to_mono_array(p_var->operator PackedVector2Array()); + } - if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) + if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) { return (MonoObject *)PackedVector3Array_to_mono_array(p_var->operator PackedVector3Array()); + } - if (array_type->eklass == CACHED_CLASS_RAW(Color)) + if (array_type->eklass == CACHED_CLASS_RAW(Color)) { return (MonoObject *)PackedColorArray_to_mono_array(p_var->operator PackedColorArray()); + } GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); - if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) { return (MonoObject *)Array_to_mono_array(p_var->operator Array(), array_type_class); + } ERR_FAIL_V_MSG(nullptr, "Attempted to convert Variant to a managed array of unmarshallable element type."); } break; @@ -624,8 +641,8 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return BOX_BOOLEAN(val); } case Variant::INT: { - int32_t val = p_var->operator signed int(); - return BOX_INT32(val); + int64_t val = p_var->operator int64_t(); + return BOX_INT64(val); } case Variant::FLOAT: { #ifdef REAL_T_IS_DOUBLE @@ -787,7 +804,6 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty } Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type, bool p_fail_with_err = true) { - ERR_FAIL_COND_V(!p_type.type_class, Variant()); switch (p_type.type_encoding) { @@ -821,100 +837,128 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type return unbox<double>(p_obj); case MONO_TYPE_STRING: { - if (p_obj == nullptr) + if (p_obj == nullptr) { return Variant(); // NIL + } return mono_string_to_godot_not_null((MonoString *)p_obj); } break; case MONO_TYPE_VALUETYPE: { GDMonoClass *vtclass = p_type.type_class; - if (vtclass == CACHED_CLASS(Vector2)) + if (vtclass == CACHED_CLASS(Vector2)) { return MARSHALLED_IN(Vector2, unbox_addr<GDMonoMarshal::M_Vector2>(p_obj)); + } - if (vtclass == CACHED_CLASS(Vector2i)) + if (vtclass == CACHED_CLASS(Vector2i)) { return MARSHALLED_IN(Vector2i, unbox_addr<GDMonoMarshal::M_Vector2i>(p_obj)); + } - if (vtclass == CACHED_CLASS(Rect2)) + if (vtclass == CACHED_CLASS(Rect2)) { return MARSHALLED_IN(Rect2, unbox_addr<GDMonoMarshal::M_Rect2>(p_obj)); + } - if (vtclass == CACHED_CLASS(Rect2i)) + if (vtclass == CACHED_CLASS(Rect2i)) { return MARSHALLED_IN(Rect2i, unbox_addr<GDMonoMarshal::M_Rect2i>(p_obj)); + } - if (vtclass == CACHED_CLASS(Transform2D)) + if (vtclass == CACHED_CLASS(Transform2D)) { return MARSHALLED_IN(Transform2D, unbox_addr<GDMonoMarshal::M_Transform2D>(p_obj)); + } - if (vtclass == CACHED_CLASS(Vector3)) + if (vtclass == CACHED_CLASS(Vector3)) { return MARSHALLED_IN(Vector3, unbox_addr<GDMonoMarshal::M_Vector3>(p_obj)); + } - if (vtclass == CACHED_CLASS(Vector3i)) + if (vtclass == CACHED_CLASS(Vector3i)) { return MARSHALLED_IN(Vector3i, unbox_addr<GDMonoMarshal::M_Vector3i>(p_obj)); + } - if (vtclass == CACHED_CLASS(Basis)) + if (vtclass == CACHED_CLASS(Basis)) { return MARSHALLED_IN(Basis, unbox_addr<GDMonoMarshal::M_Basis>(p_obj)); + } - if (vtclass == CACHED_CLASS(Quat)) + if (vtclass == CACHED_CLASS(Quat)) { return MARSHALLED_IN(Quat, unbox_addr<GDMonoMarshal::M_Quat>(p_obj)); + } - if (vtclass == CACHED_CLASS(Transform)) + if (vtclass == CACHED_CLASS(Transform)) { return MARSHALLED_IN(Transform, unbox_addr<GDMonoMarshal::M_Transform>(p_obj)); + } - if (vtclass == CACHED_CLASS(AABB)) + if (vtclass == CACHED_CLASS(AABB)) { return MARSHALLED_IN(AABB, unbox_addr<GDMonoMarshal::M_AABB>(p_obj)); + } - if (vtclass == CACHED_CLASS(Color)) + if (vtclass == CACHED_CLASS(Color)) { return MARSHALLED_IN(Color, unbox_addr<GDMonoMarshal::M_Color>(p_obj)); + } - if (vtclass == CACHED_CLASS(Plane)) + if (vtclass == CACHED_CLASS(Plane)) { return MARSHALLED_IN(Plane, unbox_addr<GDMonoMarshal::M_Plane>(p_obj)); + } - if (vtclass == CACHED_CLASS(Callable)) + if (vtclass == CACHED_CLASS(Callable)) { return managed_to_callable(unbox<GDMonoMarshal::M_Callable>(p_obj)); + } - if (vtclass == CACHED_CLASS(SignalInfo)) + if (vtclass == CACHED_CLASS(SignalInfo)) { return managed_to_signal_info(unbox<GDMonoMarshal::M_SignalInfo>(p_obj)); + } - if (mono_class_is_enum(vtclass->get_mono_ptr())) + if (mono_class_is_enum(vtclass->get_mono_ptr())) { return unbox<int32_t>(p_obj); + } } break; case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: { MonoArrayType *array_type = mono_type_get_array_type(p_type.type_class->get_mono_type()); - if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) + if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) { return mono_array_to_Array((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) + if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) { return mono_array_to_PackedByteArray((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) + if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) { return mono_array_to_PackedInt32Array((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) + if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) { return mono_array_to_PackedInt64Array((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(float)) + if (array_type->eklass == CACHED_CLASS_RAW(float)) { return mono_array_to_PackedFloat32Array((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(double)) + if (array_type->eklass == CACHED_CLASS_RAW(double)) { return mono_array_to_PackedFloat64Array((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(String)) + if (array_type->eklass == CACHED_CLASS_RAW(String)) { return mono_array_to_PackedStringArray((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) + if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) { return mono_array_to_PackedVector2Array((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) + if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) { return mono_array_to_PackedVector3Array((MonoArray *)p_obj); + } - if (array_type->eklass == CACHED_CLASS_RAW(Color)) + if (array_type->eklass == CACHED_CLASS_RAW(Color)) { return mono_array_to_PackedColorArray((MonoArray *)p_obj); + } GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); - if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) { return mono_array_to_Array((MonoArray *)p_obj); + } if (p_fail_with_err) { ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant."); @@ -1013,8 +1057,9 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type } Variant mono_object_to_variant(MonoObject *p_obj) { - if (!p_obj) + if (!p_obj) { return Variant(); + } ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj)); @@ -1022,20 +1067,26 @@ Variant mono_object_to_variant(MonoObject *p_obj) { } Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) { - if (!p_obj) + if (!p_obj) { return Variant(); + } return mono_object_to_variant_impl(p_obj, p_type); } Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_type) { - if (!p_obj) + if (!p_obj) { return Variant(); + } return mono_object_to_variant_impl(p_obj, p_type, /* fail_with_err: */ false); } String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) { + if (p_obj == nullptr) { + return String("null"); + } + ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj)); Variant var = GDMonoMarshal::mono_object_to_variant_no_err(p_obj, type); @@ -1045,8 +1096,9 @@ String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) { MonoString *mono_str = GDMonoUtils::object_to_string(p_obj, &exc); if (exc) { - if (r_exc) + if (r_exc) { *r_exc = exc; + } return String(); } @@ -1156,8 +1208,9 @@ MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_c Array mono_array_to_Array(MonoArray *p_array) { Array ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); @@ -1175,22 +1228,23 @@ MonoArray *PackedInt32Array_to_mono_array(const PackedInt32Array &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(int32_t), length); - int32_t *dst = (int32_t *)mono_array_addr(ret, int32_t, 0); - memcpy(dst, src, length); + int32_t *dst = mono_array_addr(ret, int32_t, 0); + memcpy(dst, src, length * sizeof(int32_t)); return ret; } PackedInt32Array mono_array_to_PackedInt32Array(MonoArray *p_array) { PackedInt32Array ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); int32_t *dst = ret.ptrw(); - const int32_t *src = (const int32_t *)mono_array_addr(p_array, int32_t, 0); - memcpy(dst, src, length); + const int32_t *src = mono_array_addr(p_array, int32_t, 0); + memcpy(dst, src, length * sizeof(int32_t)); return ret; } @@ -1201,22 +1255,23 @@ MonoArray *PackedInt64Array_to_mono_array(const PackedInt64Array &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(int64_t), length); - int64_t *dst = (int64_t *)mono_array_addr(ret, int64_t, 0); - memcpy(dst, src, length); + int64_t *dst = mono_array_addr(ret, int64_t, 0); + memcpy(dst, src, length * sizeof(int64_t)); return ret; } PackedInt64Array mono_array_to_PackedInt64Array(MonoArray *p_array) { PackedInt64Array ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); int64_t *dst = ret.ptrw(); - const int64_t *src = (const int64_t *)mono_array_addr(p_array, int64_t, 0); - memcpy(dst, src, length); + const int64_t *src = mono_array_addr(p_array, int64_t, 0); + memcpy(dst, src, length * sizeof(int64_t)); return ret; } @@ -1227,22 +1282,23 @@ MonoArray *PackedByteArray_to_mono_array(const PackedByteArray &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), length); - uint8_t *dst = (uint8_t *)mono_array_addr(ret, uint8_t, 0); - memcpy(dst, src, length); + uint8_t *dst = mono_array_addr(ret, uint8_t, 0); + memcpy(dst, src, length * sizeof(uint8_t)); return ret; } PackedByteArray mono_array_to_PackedByteArray(MonoArray *p_array) { PackedByteArray ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); uint8_t *dst = ret.ptrw(); - const uint8_t *src = (const uint8_t *)mono_array_addr(p_array, uint8_t, 0); - memcpy(dst, src, length); + const uint8_t *src = mono_array_addr(p_array, uint8_t, 0); + memcpy(dst, src, length * sizeof(uint8_t)); return ret; } @@ -1253,22 +1309,23 @@ MonoArray *PackedFloat32Array_to_mono_array(const PackedFloat32Array &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(float), length); - float *dst = (float *)mono_array_addr(ret, float, 0); - memcpy(dst, src, length); + float *dst = mono_array_addr(ret, float, 0); + memcpy(dst, src, length * sizeof(float)); return ret; } PackedFloat32Array mono_array_to_PackedFloat32Array(MonoArray *p_array) { PackedFloat32Array ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); float *dst = ret.ptrw(); - const float *src = (const float *)mono_array_addr(p_array, float, 0); - memcpy(dst, src, length); + const float *src = mono_array_addr(p_array, float, 0); + memcpy(dst, src, length * sizeof(float)); return ret; } @@ -1279,22 +1336,23 @@ MonoArray *PackedFloat64Array_to_mono_array(const PackedFloat64Array &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(double), length); - double *dst = (double *)mono_array_addr(ret, double, 0); - memcpy(dst, src, length); + double *dst = mono_array_addr(ret, double, 0); + memcpy(dst, src, length * sizeof(double)); return ret; } PackedFloat64Array mono_array_to_PackedFloat64Array(MonoArray *p_array) { PackedFloat64Array ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); double *dst = ret.ptrw(); - const double *src = (const double *)mono_array_addr(p_array, double, 0); - memcpy(dst, src, length); + const double *src = mono_array_addr(p_array, double, 0); + memcpy(dst, src, length * sizeof(double)); return ret; } @@ -1315,8 +1373,9 @@ MonoArray *PackedStringArray_to_mono_array(const PackedStringArray &p_array) { PackedStringArray mono_array_to_PackedStringArray(MonoArray *p_array) { PackedStringArray ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); String *w = ret.ptrw(); @@ -1336,8 +1395,8 @@ MonoArray *PackedColorArray_to_mono_array(const PackedColorArray &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Color), length); if constexpr (InteropLayout::MATCHES_Color) { - Color *dst = (Color *)mono_array_addr(ret, Color, 0); - memcpy(dst, src, length); + Color *dst = mono_array_addr(ret, Color, 0); + memcpy(dst, src, length * sizeof(Color)); } else { for (int i = 0; i < length; i++) { M_Color *raw = (M_Color *)mono_array_addr_with_size(ret, sizeof(M_Color), i); @@ -1350,15 +1409,16 @@ MonoArray *PackedColorArray_to_mono_array(const PackedColorArray &p_array) { PackedColorArray mono_array_to_PackedColorArray(MonoArray *p_array) { PackedColorArray ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); Color *dst = ret.ptrw(); if constexpr (InteropLayout::MATCHES_Color) { - const Color *src = (const Color *)mono_array_addr(p_array, Color, 0); - memcpy(dst, src, length); + const Color *src = mono_array_addr(p_array, Color, 0); + memcpy(dst, src, length * sizeof(Color)); } else { for (int i = 0; i < length; i++) { dst[i] = MARSHALLED_IN(Color, (M_Color *)mono_array_addr_with_size(p_array, sizeof(M_Color), i)); @@ -1375,8 +1435,8 @@ MonoArray *PackedVector2Array_to_mono_array(const PackedVector2Array &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector2), length); if constexpr (InteropLayout::MATCHES_Vector2) { - Vector2 *dst = (Vector2 *)mono_array_addr(ret, Vector2, 0); - memcpy(dst, src, length); + Vector2 *dst = mono_array_addr(ret, Vector2, 0); + memcpy(dst, src, length * sizeof(Vector2)); } else { for (int i = 0; i < length; i++) { M_Vector2 *raw = (M_Vector2 *)mono_array_addr_with_size(ret, sizeof(M_Vector2), i); @@ -1389,15 +1449,16 @@ MonoArray *PackedVector2Array_to_mono_array(const PackedVector2Array &p_array) { PackedVector2Array mono_array_to_PackedVector2Array(MonoArray *p_array) { PackedVector2Array ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); Vector2 *dst = ret.ptrw(); if constexpr (InteropLayout::MATCHES_Vector2) { - const Vector2 *src = (const Vector2 *)mono_array_addr(p_array, Vector2, 0); - memcpy(dst, src, length); + const Vector2 *src = mono_array_addr(p_array, Vector2, 0); + memcpy(dst, src, length * sizeof(Vector2)); } else { for (int i = 0; i < length; i++) { dst[i] = MARSHALLED_IN(Vector2, (M_Vector2 *)mono_array_addr_with_size(p_array, sizeof(M_Vector2), i)); @@ -1414,8 +1475,8 @@ MonoArray *PackedVector3Array_to_mono_array(const PackedVector3Array &p_array) { MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector3), length); if constexpr (InteropLayout::MATCHES_Vector3) { - Vector3 *dst = (Vector3 *)mono_array_addr(ret, Vector3, 0); - memcpy(dst, src, length); + Vector3 *dst = mono_array_addr(ret, Vector3, 0); + memcpy(dst, src, length * sizeof(Vector3)); } else { for (int i = 0; i < length; i++) { M_Vector3 *raw = (M_Vector3 *)mono_array_addr_with_size(ret, sizeof(M_Vector3), i); @@ -1428,15 +1489,16 @@ MonoArray *PackedVector3Array_to_mono_array(const PackedVector3Array &p_array) { PackedVector3Array mono_array_to_PackedVector3Array(MonoArray *p_array) { PackedVector3Array ret; - if (!p_array) + if (!p_array) { return ret; + } int length = mono_array_length(p_array); ret.resize(length); Vector3 *dst = ret.ptrw(); if constexpr (InteropLayout::MATCHES_Vector3) { - const Vector3 *src = (const Vector3 *)mono_array_addr(p_array, Vector3, 0); - memcpy(dst, src, length); + const Vector3 *src = mono_array_addr(p_array, Vector3, 0); + memcpy(dst, src, length * sizeof(Vector3)); } else { for (int i = 0; i < length; i++) { dst[i] = MARSHALLED_IN(Vector3, (M_Vector3 *)mono_array_addr_with_size(p_array, sizeof(M_Vector3), i)); diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index f2d887e6d6..4ff330fd43 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -66,7 +66,6 @@ T *unbox_addr(MonoObject *p_obj) { Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_variant = nullptr); bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type); -bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, ManagedType &r_key_type, ManagedType &r_value_type); // String @@ -74,15 +73,17 @@ String mono_to_utf8_string(MonoString *p_mono_string); String mono_to_utf16_string(MonoString *p_mono_string); _FORCE_INLINE_ String mono_string_to_godot_not_null(MonoString *p_mono_string) { - if (sizeof(CharType) == 2) + if constexpr (sizeof(CharType) == 2) { return mono_to_utf16_string(p_mono_string); + } return mono_to_utf8_string(p_mono_string); } _FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { - if (p_mono_string == nullptr) + if (p_mono_string == nullptr) { return String(); + } return mono_string_to_godot_not_null(p_mono_string); } @@ -96,8 +97,9 @@ _FORCE_INLINE_ MonoString *mono_from_utf16_string(const String &p_string) { } _FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) { - if (sizeof(CharType) == 2) + if constexpr (sizeof(CharType) == 2) { return mono_from_utf16_string(p_string); + } return mono_from_utf8_string(p_string); } diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp index 432aa74a6f..04f3b25a70 100644 --- a/modules/mono/mono_gd/gd_mono_method.cpp +++ b/modules/mono/mono_gd/gd_mono_method.cpp @@ -155,11 +155,13 @@ MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, Mono bool GDMonoMethod::has_attribute(GDMonoClass *p_attr_class) { ERR_FAIL_NULL_V(p_attr_class, false); - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return false; + } return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); } @@ -167,11 +169,13 @@ bool GDMonoMethod::has_attribute(GDMonoClass *p_attr_class) { MonoObject *GDMonoMethod::get_attribute(GDMonoClass *p_attr_class) { ERR_FAIL_NULL_V(p_attr_class, nullptr); - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return nullptr; + } return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } @@ -245,14 +249,14 @@ void GDMonoMethod::get_parameter_types(Vector<ManagedType> &types) const { } const MethodInfo &GDMonoMethod::get_method_info() { - if (!method_info_fetched) { method_info.name = name; bool nil_is_variant = false; method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type, &nil_is_variant), ""); - if (method_info.return_val.type == Variant::NIL && nil_is_variant) + if (method_info.return_val.type == Variant::NIL && nil_is_variant) { method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } Vector<StringName> names; get_parameter_names(names); @@ -260,8 +264,9 @@ const MethodInfo &GDMonoMethod::get_method_info() { for (int i = 0; i < params_count; ++i) { nil_is_variant = false; PropertyInfo arg_info = PropertyInfo(GDMonoMarshal::managed_to_variant_type(param_types[i], &nil_is_variant), names[i]); - if (arg_info.type == Variant::NIL && nil_is_variant) + if (arg_info.type == Variant::NIL && nil_is_variant) { arg_info.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } method_info.arguments.push_back(arg_info); } diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h index 54b2eba3e8..f78f57dca0 100644 --- a/modules/mono/mono_gd/gd_mono_method.h +++ b/modules/mono/mono_gd/gd_mono_method.h @@ -36,7 +36,6 @@ #include "i_mono_class_member.h" class GDMonoMethod : public IMonoClassMember { - StringName name; int params_count; diff --git a/modules/mono/mono_gd/gd_mono_method_thunk.h b/modules/mono/mono_gd/gd_mono_method_thunk.h index 0e05e974e9..01f3ae342a 100644 --- a/modules/mono/mono_gd/gd_mono_method_thunk.h +++ b/modules/mono/mono_gd/gd_mono_method_thunk.h @@ -47,10 +47,9 @@ template <class... ParamTypes> struct GDMonoMethodThunk { - typedef void(GD_MONO_STDCALL *M)(ParamTypes... p_args, MonoException **); - M mono_method_thunk; + M mono_method_thunk = nullptr; public: _FORCE_INLINE_ void invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -81,9 +80,7 @@ public: mono_method_thunk = (M)mono_method_get_unmanaged_thunk(p_mono_method->get_mono_ptr()); } - GDMonoMethodThunk() : - mono_method_thunk(nullptr) { - } + GDMonoMethodThunk() {} explicit GDMonoMethodThunk(GDMonoMethod *p_mono_method) { set_from_method(p_mono_method); @@ -92,10 +89,9 @@ public: template <class R, class... ParamTypes> struct GDMonoMethodThunkR { - typedef R(GD_MONO_STDCALL *M)(ParamTypes... p_args, MonoException **); - M mono_method_thunk; + M mono_method_thunk = nullptr; public: _FORCE_INLINE_ R invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -127,9 +123,7 @@ public: mono_method_thunk = (M)mono_method_get_unmanaged_thunk(p_mono_method->get_mono_ptr()); } - GDMonoMethodThunkR() : - mono_method_thunk(nullptr) { - } + GDMonoMethodThunkR() {} explicit GDMonoMethodThunkR(GDMonoMethod *p_mono_method) { #ifdef DEBUG_ENABLED @@ -247,8 +241,7 @@ struct VariadicInvokeMonoMethodR<1, R, P1> { template <class... ParamTypes> struct GDMonoMethodThunk { - - GDMonoMethod *mono_method; + GDMonoMethod *mono_method = nullptr; public: _FORCE_INLINE_ void invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -277,9 +270,7 @@ public: mono_method = p_mono_method; } - GDMonoMethodThunk() : - mono_method(nullptr) { - } + GDMonoMethodThunk() {} explicit GDMonoMethodThunk(GDMonoMethod *p_mono_method) { set_from_method(p_mono_method); @@ -288,8 +279,7 @@ public: template <class R, class... ParamTypes> struct GDMonoMethodThunkR { - - GDMonoMethod *mono_method; + GDMonoMethod *mono_method = nullptr; public: _FORCE_INLINE_ R invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -318,9 +308,7 @@ public: mono_method = p_mono_method; } - GDMonoMethodThunkR() : - mono_method(nullptr) { - } + GDMonoMethodThunkR() {} explicit GDMonoMethodThunkR(GDMonoMethod *p_mono_method) { set_from_method(p_mono_method); diff --git a/modules/mono/mono_gd/gd_mono_property.cpp b/modules/mono/mono_gd/gd_mono_property.cpp index c3e7598f2d..bc3be97102 100644 --- a/modules/mono/mono_gd/gd_mono_property.cpp +++ b/modules/mono/mono_gd/gd_mono_property.cpp @@ -77,15 +77,17 @@ GDMonoProperty::~GDMonoProperty() { bool GDMonoProperty::is_static() { MonoMethod *prop_method = mono_property_get_get_method(mono_property); - if (prop_method == nullptr) + if (prop_method == nullptr) { prop_method = mono_property_get_set_method(mono_property); + } return mono_method_get_flags(prop_method, nullptr) & MONO_METHOD_ATTR_STATIC; } IMonoClassMember::Visibility GDMonoProperty::get_visibility() { MonoMethod *prop_method = mono_property_get_get_method(mono_property); - if (prop_method == nullptr) + if (prop_method == nullptr) { prop_method = mono_property_get_set_method(mono_property); + } switch (mono_method_get_flags(prop_method, nullptr) & MONO_METHOD_ATTR_ACCESS_MASK) { case MONO_METHOD_ATTR_PRIVATE: @@ -106,11 +108,13 @@ IMonoClassMember::Visibility GDMonoProperty::get_visibility() { bool GDMonoProperty::has_attribute(GDMonoClass *p_attr_class) { ERR_FAIL_NULL_V(p_attr_class, false); - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return false; + } return mono_custom_attrs_has_attr(attributes, p_attr_class->get_mono_ptr()); } @@ -118,11 +122,13 @@ bool GDMonoProperty::has_attribute(GDMonoClass *p_attr_class) { MonoObject *GDMonoProperty::get_attribute(GDMonoClass *p_attr_class) { ERR_FAIL_NULL_V(p_attr_class, nullptr); - if (!attrs_fetched) + if (!attrs_fetched) { fetch_attributes(); + } - if (!attributes) + if (!attributes) { return nullptr; + } return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h index 4653758a86..611ac293e4 100644 --- a/modules/mono/mono_gd/gd_mono_property.h +++ b/modules/mono/mono_gd/gd_mono_property.h @@ -36,7 +36,6 @@ #include "i_mono_class_member.h" class GDMonoProperty : public IMonoClassMember { - GDMonoClass *owner; MonoProperty *mono_property; diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index f9d492dabb..3f1155f430 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -38,7 +38,6 @@ #include "core/os/dir_access.h" #include "core/os/mutex.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "core/reference.h" #ifdef TOOLS_ENABLED @@ -51,14 +50,13 @@ #include "gd_mono_cache.h" #include "gd_mono_class.h" #include "gd_mono_marshal.h" -#include "gd_mono_method_thunk.h" namespace GDMonoUtils { MonoObject *unmanaged_get_managed(Object *unmanaged) { - - if (!unmanaged) + if (!unmanaged) { return nullptr; + } if (unmanaged->get_script_instance()) { CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance()); @@ -91,8 +89,9 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { MonoObject *target = gchandle.get_target(); - if (target) + if (target) { return target; + } CSharpLanguage::get_singleton()->release_script_gchandle(gchandle); @@ -197,8 +196,9 @@ GDMonoClass *get_object_class(MonoObject *p_object) { GDMonoClass *type_get_proxy_class(const StringName &p_type) { String class_name = p_type; - if (class_name[0] == '_') + if (class_name[0] == '_') { class_name = class_name.substr(1, class_name.length()); + } GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); @@ -221,11 +221,14 @@ GDMonoClass *get_class_native_base(GDMonoClass *p_class) { do { const GDMonoAssembly *assembly = klass->get_assembly(); - if (assembly == GDMono::get_singleton()->get_core_api_assembly()) + + if (assembly == GDMono::get_singleton()->get_core_api_assembly()) { return klass; + } #ifdef TOOLS_ENABLED - if (assembly == GDMono::get_singleton()->get_editor_api_assembly()) + if (assembly == GDMono::get_singleton()->get_editor_api_assembly()) { return klass; + } #endif } while ((klass = klass->get_parent_class()) != nullptr); @@ -386,14 +389,6 @@ String get_exception_name_and_message(MonoException *p_exc) { return res; } -void set_exception_message(MonoException *p_exc, String message) { - MonoClass *klass = mono_object_get_class((MonoObject *)p_exc); - MonoProperty *prop = mono_class_get_property_from_name(klass, "Message"); - MonoString *msg = GDMonoMarshal::mono_string_from_godot(message); - void *params[1] = { msg }; - property_set_value(prop, (MonoObject *)p_exc, params, nullptr); -} - void debug_print_unhandled_exception(MonoException *p_exc) { print_unhandled_exception(p_exc); debug_send_unhandled_exception_error(p_exc); @@ -411,8 +406,9 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { } static thread_local bool _recursion_flag_ = false; - if (_recursion_flag_) + if (_recursion_flag_) { return; + } _recursion_flag_ = true; SCOPE_EXIT { _recursion_flag_ = false; }; @@ -442,8 +438,9 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { Vector<ScriptLanguage::StackInfo> _si; if (stack_trace != nullptr) { _si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); - for (int i = _si.size() - 1; i >= 0; i--) + for (int i = _si.size() - 1; i >= 0; i--) { si.insert(0, _si[i]); + } } exc_msg += (exc_msg.length() > 0 ? " ---> " : "") + GDMonoUtils::get_exception_name_and_message(p_exc); @@ -453,8 +450,9 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { CRASH_COND(inner_exc_prop == nullptr); MonoObject *inner_exc = inner_exc_prop->get_value((MonoObject *)p_exc); - if (inner_exc != nullptr) + if (inner_exc != nullptr) { si.insert(0, separator); + } p_exc = (MonoException *)inner_exc; } @@ -564,9 +562,10 @@ namespace Marshal { #ifdef MONO_GLUE_ENABLED #ifdef TOOLS_ENABLED -#define NO_GLUE_RET(m_ret) \ - { \ - if (!GDMonoCache::cached_data.godot_api_cache_updated) return m_ret; \ +#define NO_GLUE_RET(m_ret) \ + { \ + if (!GDMonoCache::cached_data.godot_api_cache_updated) \ + return m_ret; \ } #else #define NO_GLUE_RET(m_ret) \ @@ -663,8 +662,7 @@ GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, Mon } // namespace Marshal -ScopeThreadAttach::ScopeThreadAttach() : - mono_thread(nullptr) { +ScopeThreadAttach::ScopeThreadAttach() { if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) { mono_thread = GDMonoUtils::attach_current_thread(); } diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index e3011ade5d..9db4a5f3f0 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -84,10 +84,6 @@ void detach_current_thread(MonoThread *p_mono_thread); MonoThread *get_current_thread(); bool is_thread_attached(); -_FORCE_INLINE_ bool is_main_thread() { - return mono_domain_get() != nullptr && mono_thread_get_main() == mono_thread_current(); -} - uint32_t new_strong_gchandle(MonoObject *p_object); uint32_t new_strong_gchandle_pinned(MonoObject *p_object); uint32_t new_weak_gchandle(MonoObject *p_object); @@ -115,7 +111,6 @@ String get_type_desc(MonoType *p_type); String get_type_desc(MonoReflectionType *p_reftype); String get_exception_name_and_message(MonoException *p_exc); -void set_exception_message(MonoException *p_exc, String message); void debug_print_unhandled_exception(MonoException *p_exc); void debug_send_unhandled_exception_error(MonoException *p_exc); @@ -134,6 +129,7 @@ extern thread_local int current_invoke_count; _FORCE_INLINE_ int get_runtime_invoke_count() { return current_invoke_count; } + _FORCE_INLINE_ int &get_runtime_invoke_count_ref() { return current_invoke_count; } @@ -155,7 +151,7 @@ struct ScopeThreadAttach { ~ScopeThreadAttach(); private: - MonoThread *mono_thread; + MonoThread *mono_thread = nullptr; }; StringName get_native_godot_class_name(GDMonoClass *p_class); diff --git a/modules/mono/mono_gd/managed_type.h b/modules/mono/mono_gd/managed_type.h index 84d1837853..491a2f3d20 100644 --- a/modules/mono/mono_gd/managed_type.h +++ b/modules/mono/mono_gd/managed_type.h @@ -36,18 +36,15 @@ #include "gd_mono_header.h" struct ManagedType { - int type_encoding; - GDMonoClass *type_class; + int type_encoding = 0; + GDMonoClass *type_class = nullptr; static ManagedType from_class(GDMonoClass *p_class); static ManagedType from_class(MonoClass *p_mono_class); static ManagedType from_type(MonoType *p_mono_type); static ManagedType from_reftype(MonoReflectionType *p_mono_reftype); - ManagedType() : - type_encoding(0), - type_class(nullptr) { - } + ManagedType() {} ManagedType(int p_type_encoding, GDMonoClass *p_type_class) : type_encoding(p_type_encoding), diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp index 8bcdeec9dd..8bcdeec9dd 100755..100644 --- a/modules/mono/mono_gd/support/android_support.cpp +++ b/modules/mono/mono_gd/support/android_support.cpp diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm index e3d1a647fd..e3d1a647fd 100755..100644 --- a/modules/mono/mono_gd/support/ios_support.mm +++ b/modules/mono/mono_gd/support/ios_support.mm |