diff options
Diffstat (limited to 'modules/mono/mono_gd/gd_mono.cpp')
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 446 |
1 files changed, 42 insertions, 404 deletions
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index bf387be4c8..ce4fc0c5a0 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -48,8 +48,6 @@ #include "../godotsharp_dirs.h" #include "../utils/path_utils.h" #include "gd_mono_cache.h" -#include "gd_mono_class.h" -#include "gd_mono_marshal.h" #include "gd_mono_utils.h" #ifdef ANDROID_ENABLED @@ -411,7 +409,9 @@ void GDMono::initialize_load_assemblies() { // Load assemblies. The API and tools assemblies are required, // the application is aborted if these assemblies cannot be loaded. - _load_api_assemblies(); + if (!_try_load_api_assemblies()) { + CRASH_NOW_MSG("Failed to load one of the API assemblies."); + } #if defined(TOOLS_ENABLED) bool tool_assemblies_loaded = _load_tools_assemblies(); @@ -432,24 +432,12 @@ void GDMono::initialize_load_assemblies() { } } -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) { - out_of_sync = editor_api_assembly.assembly && editor_api_assembly.out_of_sync; - } -#endif - return out_of_sync; -} - void godot_register_object_icalls(); -void godot_register_scene_tree_icalls(); void godot_register_placeholder_icalls(); void GDMono::_register_internal_calls() { // Registers internal calls that were not generated. godot_register_object_icalls(); - godot_register_scene_tree_icalls(); godot_register_placeholder_icalls(); } @@ -490,35 +478,35 @@ GDMonoAssembly *GDMono::get_loaded_assembly(const String &p_name) { return result ? *result : nullptr; } -bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) { +bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly) { #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); + bool result = load_assembly(p_name, aname, r_assembly); mono_assembly_name_free(aname); mono_free(aname); return result; } -bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly) { #ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); #endif - return load_assembly(p_name, p_aname, r_assembly, p_refonly, GDMonoAssembly::get_default_search_dirs()); + return load_assembly(p_name, p_aname, r_assembly, 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) { +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, const Vector<String> &p_search_dirs) { #ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); #endif - print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); + print_verbose("Mono: Loading assembly " + p_name + "..."); - GDMonoAssembly *assembly = GDMonoAssembly::load(p_name, p_aname, p_refonly, p_search_dirs); + GDMonoAssembly *assembly = GDMonoAssembly::load(p_name, p_aname, /* refonly: */ false, p_search_dirs); if (!assembly) { return false; @@ -526,17 +514,17 @@ bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMo *r_assembly = assembly; - print_verbose("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path()); + print_verbose("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path()); return true; } -bool GDMono::load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly, bool p_refonly) { +bool GDMono::load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly) { CRASH_COND(!r_assembly); - print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); + print_verbose("Mono: Loading assembly " + p_name + "..."); - GDMonoAssembly *assembly = GDMonoAssembly::load_from(p_name, p_path, p_refonly); + GDMonoAssembly *assembly = GDMonoAssembly::load_from(p_name, p_path, /* refonly: */ false); if (!assembly) { return false; @@ -544,279 +532,41 @@ bool GDMono::load_assembly_from(const String &p_name, const String &p_path, GDMo *r_assembly = assembly; - print_verbose("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path()); + print_verbose("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path()); return true; } -ApiAssemblyInfo::Version ApiAssemblyInfo::Version::get_from_loaded_assembly(GDMonoAssembly *p_api_assembly, ApiAssemblyInfo::Type p_api_type) { - ApiAssemblyInfo::Version api_assembly_version; - - const char *nativecalls_name = p_api_type == ApiAssemblyInfo::API_CORE - ? BINDINGS_CLASS_NATIVECALLS - : BINDINGS_CLASS_NATIVECALLS_EDITOR; - - GDMonoClass *nativecalls_klass = p_api_assembly->get_class(BINDINGS_NAMESPACE, nativecalls_name); - - if (nativecalls_klass) { - GDMonoField *api_hash_field = nativecalls_klass->get_field("godot_api_hash"); - if (api_hash_field) { - api_assembly_version.godot_api_hash = GDMonoMarshal::unbox<uint64_t>(api_hash_field->get_value(nullptr)); - } - } - - return api_assembly_version; -} - -String ApiAssemblyInfo::to_string(ApiAssemblyInfo::Type p_type) { - return p_type == ApiAssemblyInfo::API_CORE ? "API_CORE" : "API_EDITOR"; -} - bool GDMono::_load_corlib_assembly() { if (corlib_assembly) { return true; } - bool success = load_assembly("mscorlib", &corlib_assembly); - - 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); - - String assembly_name = p_api_type == ApiAssemblyInfo::API_CORE ? CORE_API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME; - - // Create destination directory if needed - if (!DirAccess::exists(dst_dir)) { - Ref<DirAccess> da = DirAccess::create_for_path(dst_dir); - Error err = da->make_dir_recursive(dst_dir); - - if (err != OK) { - ERR_PRINT("Failed to create destination directory for the API assemblies. Error: " + itos(err) + "."); - return false; - } - } - - Ref<DirAccess> 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) { - 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) { - 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) { - ERR_PRINT("Failed to copy '" + assembly_file + "'."); - return false; - } - - return true; -} - -static bool try_get_cached_api_hash_for(const String &p_api_assemblies_dir, bool &r_out_of_sync) { - 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)) { - return false; - } - - String cached_api_hash_path = p_api_assemblies_dir.plus_file("api_hash_cache.cfg"); - - if (!FileAccess::exists(cached_api_hash_path)) { - return false; - } - - Ref<ConfigFile> cfg; - cfg.instantiate(); - Error cfg_err = cfg->load(cached_api_hash_path); - ERR_FAIL_COND_V(cfg_err != OK, false); - - // Checking the modified time is good enough - if (FileAccess::get_modified_time(core_api_assembly_path) != (uint64_t)cfg->get_value("core", "modified_time") || - FileAccess::get_modified_time(editor_api_assembly_path) != (uint64_t)cfg->get_value("editor", "modified_time")) { - return false; - } - - r_out_of_sync = GDMono::get_singleton()->get_api_core_hash() != (uint64_t)cfg->get_value("core", "api_hash") || - GDMono::get_singleton()->get_api_editor_hash() != (uint64_t)cfg->get_value("editor", "api_hash"); - - return true; -} - -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"); - - Ref<ConfigFile> cfg; - cfg.instantiate(); - - cfg->set_value("core", "modified_time", FileAccess::get_modified_time(core_api_assembly_path)); - cfg->set_value("editor", "modified_time", FileAccess::get_modified_time(editor_api_assembly_path)); - - // This assumes the prebuilt api assemblies we copied to the project are not out of sync - cfg->set_value("core", "api_hash", GDMono::get_singleton()->get_api_core_hash()); - cfg->set_value("editor", "api_hash", GDMono::get_singleton()->get_api_editor_hash()); - - Error err = cfg->save(cached_api_hash_path); - ERR_FAIL_COND(err != OK); -} - -bool GDMono::_temp_domain_load_are_assemblies_out_of_sync(const String &p_config) { - MonoDomain *temp_domain = GDMonoUtils::create_domain("GodotEngine.Domain.CheckApiAssemblies"); - ERR_FAIL_NULL_V(temp_domain, "Failed to create temporary domain to check API assemblies"); - _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(temp_domain); - - _GDMONO_SCOPE_DOMAIN_(temp_domain); - - GDMono::LoadedApiAssembly temp_core_api_assembly; - GDMono::LoadedApiAssembly temp_editor_api_assembly; - - if (!_try_load_api_assemblies(temp_core_api_assembly, temp_editor_api_assembly, - p_config, /* refonly: */ true, /* loaded_callback: */ nullptr)) { - return temp_core_api_assembly.out_of_sync || temp_editor_api_assembly.out_of_sync; - } - - return true; // Failed to load, assume they're outdated assemblies -} - -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 ? String("The assembly is invalidated ") : String("The assembly was not found ")) + \ - (m_prebuilt_exists ? String("and the prebuilt assemblies are missing.") : String("and we failed to copy the prebuilt assemblies."))) - - String dst_assemblies_dir = GodotSharpDirs::get_res_assemblies_base_dir().plus_file(p_config); - - String core_assembly_path = dst_assemblies_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll"); - String editor_assembly_path = dst_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); - - bool api_assemblies_out_of_sync = false; - - if (p_core_api_out_of_sync && p_editor_api_out_of_sync) { - api_assemblies_out_of_sync = *p_core_api_out_of_sync || *p_editor_api_out_of_sync; - } else if (FileAccess::exists(core_assembly_path) && FileAccess::exists(editor_assembly_path)) { - // Determine if they're out of sync - if (!try_get_cached_api_hash_for(dst_assemblies_dir, api_assemblies_out_of_sync)) { - api_assemblies_out_of_sync = _temp_domain_load_are_assemblies_out_of_sync(p_config); - } - } - - // 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)) { - return String(); // No update needed - } - - print_verbose("Updating '" + p_config + "' API assemblies"); - - String prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file(p_config); - String prebuilt_core_dll_path = prebuilt_api_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll"); - String prebuilt_editor_dll_path = prebuilt_api_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); - - if (!FileAccess::exists(prebuilt_core_dll_path) || !FileAccess::exists(prebuilt_editor_dll_path)) { - return FAIL_REASON(api_assemblies_out_of_sync, /* prebuilt_exists: */ false); - } - - // Copy the prebuilt Api - if (!copy_prebuilt_api_assembly(ApiAssemblyInfo::API_CORE, p_config) || - !copy_prebuilt_api_assembly(ApiAssemblyInfo::API_EDITOR, p_config)) { - return FAIL_REASON(api_assemblies_out_of_sync, /* prebuilt_exists: */ true); - } - - // Cache the api hash of the assemblies we just copied - create_cached_api_hash_for(dst_assemblies_dir); - - return String(); // Updated successfully - -#undef FAIL_REASON + return load_assembly("mscorlib", &corlib_assembly); } -#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) { +bool GDMono::_load_core_api_assembly(GDMonoAssembly **r_loaded_api_assembly, const String &p_config) { + if (*r_loaded_api_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 - - // If running the project manager, load it from the prebuilt API directory - String assembly_dir = !Engine::get_singleton()->is_project_manager_hint() - ? GodotSharpDirs::get_res_assemblies_base_dir().plus_file(p_config) - : GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file(p_config); - - String assembly_path = assembly_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll"); - - bool success = FileAccess::exists(assembly_path) && - load_assembly_from(CORE_API_ASSEMBLY_NAME, assembly_path, &r_loaded_api_assembly.assembly, p_refonly); -#else - bool success = load_assembly(CORE_API_ASSEMBLY_NAME, &r_loaded_api_assembly.assembly, p_refonly); -#endif - -#ifdef DEBUG_METHODS_ENABLED - if (success) { - ApiAssemblyInfo::Version api_assembly_ver = ApiAssemblyInfo::Version::get_from_loaded_assembly(r_loaded_api_assembly.assembly, ApiAssemblyInfo::API_CORE); - r_loaded_api_assembly.out_of_sync = get_api_core_hash() != api_assembly_ver.godot_api_hash; - } else { - r_loaded_api_assembly.out_of_sync = false; - } -#else - r_loaded_api_assembly.out_of_sync = false; -#endif - - return success; + return load_assembly(CORE_API_ASSEMBLY_NAME, r_loaded_api_assembly); } #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) { +bool GDMono::_load_editor_api_assembly(GDMonoAssembly **r_loaded_api_assembly, const String &p_config) { + if (*r_loaded_api_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 - - // If running the project manager, load it from the prebuilt API directory - String assembly_dir = !Engine::get_singleton()->is_project_manager_hint() - ? GodotSharpDirs::get_res_assemblies_base_dir().plus_file(p_config) - : GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file(p_config); - - String assembly_path = assembly_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); - - bool success = FileAccess::exists(assembly_path) && - load_assembly_from(EDITOR_API_ASSEMBLY_NAME, assembly_path, &r_loaded_api_assembly.assembly, p_refonly); - -#ifdef DEBUG_METHODS_ENABLED - if (success) { - ApiAssemblyInfo::Version api_assembly_ver = ApiAssemblyInfo::Version::get_from_loaded_assembly(r_loaded_api_assembly.assembly, ApiAssemblyInfo::API_EDITOR); - r_loaded_api_assembly.out_of_sync = get_api_editor_hash() != api_assembly_ver.godot_api_hash; - } else { - r_loaded_api_assembly.out_of_sync = false; - } -#else - r_loaded_api_assembly.out_of_sync = false; -#endif - - return success; + return load_assembly(EDITOR_API_ASSEMBLY_NAME, r_loaded_api_assembly); } #endif -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)) { +bool GDMono::_try_load_api_assemblies() { + String config = get_expected_api_build_config(); + + if (!_load_core_api_assembly(&core_api_assembly, config)) { if (OS::get_singleton()->is_stdout_verbose()) { print_error("Mono: Failed to load Core API assembly"); } @@ -824,30 +574,15 @@ bool GDMono::_try_load_api_assemblies(LoadedApiAssembly &r_core_api_assembly, Lo } #ifdef TOOLS_ENABLED - if (!_load_editor_api_assembly(r_editor_api_assembly, p_config, p_refonly)) { + if (!_load_editor_api_assembly(&editor_api_assembly, config)) { 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) { - 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) { - return false; - } - - if (p_callback) { - return p_callback(); - } - - return true; + return _on_core_api_assembly_loaded(); } bool GDMono::_on_core_api_assembly_loaded() { @@ -862,72 +597,14 @@ bool GDMono::_on_core_api_assembly_loaded() { return true; } -bool GDMono::_try_load_api_assemblies_preset() { - return _try_load_api_assemblies(core_api_assembly, editor_api_assembly, - get_expected_api_build_config(), /* refonly: */ false, _on_core_api_assembly_loaded); -} - -void GDMono::_load_api_assemblies() { - bool api_assemblies_loaded = _try_load_api_assemblies_preset(); - -#if defined(TOOLS_ENABLED) && !defined(GD_MONO_SINGLE_APPDOMAIN) - if (!api_assemblies_loaded) { - // The API assemblies are out of sync or some other error happened. Fine, try one more time, but - // this time update them from the prebuilt assemblies directory before trying to load them again. - - // Shouldn't happen. The project manager loads the prebuilt API assemblies - CRASH_COND_MSG(Engine::get_singleton()->is_project_manager_hint(), "Failed to load one of the prebuilt API assemblies."); - - // 1. Unload the scripts domain - Error domain_unload_err = _unload_scripts_domain(); - CRASH_COND_MSG(domain_unload_err != OK, "Mono: Failed to unload scripts domain."); - - // 2. Update the API assemblies - String update_error = update_api_assemblies_from_prebuilt("Debug", &core_api_assembly.out_of_sync, &editor_api_assembly.out_of_sync); - CRASH_COND_MSG(!update_error.is_empty(), update_error); - - // 3. Load the scripts domain again - Error domain_load_err = _load_scripts_domain(); - CRASH_COND_MSG(domain_load_err != OK, "Mono: Failed to load scripts domain."); - - // 4. Try loading the updated assemblies - api_assemblies_loaded = _try_load_api_assemblies_preset(); - } -#endif - - if (!api_assemblies_loaded) { - // welp... too bad - - if (_are_api_assemblies_out_of_sync()) { - if (core_api_assembly.out_of_sync) { - ERR_PRINT("The assembly '" CORE_API_ASSEMBLY_NAME "' is out of sync."); - } else if (!GDMonoCache::cached_data.godot_api_cache_updated) { - ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed."); - } - -#ifdef TOOLS_ENABLED - if (editor_api_assembly.out_of_sync) { - ERR_PRINT("The assembly '" EDITOR_API_ASSEMBLY_NAME "' is out of sync."); - } -#endif - - CRASH_NOW(); - } else { - CRASH_NOW_MSG("Failed to load one of the API assemblies."); - } - } -} - #ifdef TOOLS_ENABLED bool GDMono::_load_tools_assemblies() { 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); - - return success; + return load_assembly(TOOLS_ASM_NAME, &tools_assembly) && + load_assembly(TOOLS_PROJECT_EDITOR_ASM_NAME, &tools_project_editor_assembly); } #endif @@ -946,7 +623,12 @@ bool GDMono::_load_project_assembly() { if (success) { mono_assembly_set_main(project_assembly->get_assembly()); - CSharpLanguage::get_singleton()->lookup_scripts_in_assembly(project_assembly); + MonoException *exc = nullptr; + GDMonoCache::cached_data.methodthunk_ScriptManagerBridge_LookupScriptsInAssembly.invoke( + mono_assembly_get_object(mono_domain_get(), project_assembly->get_assembly()), &exc); + if (exc) { + GDMonoUtils::debug_print_unhandled_exception(exc); + } } return success; @@ -955,11 +637,8 @@ 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"); - GDMonoMethod *install_func = debug_utils->get_method("InstallTraceListener"); - MonoException *exc = nullptr; - install_func->invoke_raw(nullptr, nullptr, &exc); + GDMonoCache::cached_data.methodthunk_DebuggingUtils_InstallTraceListener.invoke(&exc); if (exc) { GDMonoUtils::debug_print_unhandled_exception(exc); ERR_PRINT("Failed to install 'System.Diagnostics.Trace' listener."); @@ -1007,9 +686,9 @@ Error GDMono::_unload_scripts_domain() { _domain_assemblies_cleanup(mono_domain_get_id(scripts_domain)); - core_api_assembly.assembly = nullptr; + core_api_assembly = nullptr; #ifdef TOOLS_ENABLED - editor_api_assembly.assembly = nullptr; + editor_api_assembly = nullptr; #endif project_assembly = nullptr; @@ -1051,7 +730,9 @@ Error GDMono::reload_scripts_domain() { // Load assemblies. The API and tools assemblies are required, // the application is aborted if these assemblies cannot be loaded. - _load_api_assemblies(); + if (!_try_load_api_assemblies()) { + CRASH_NOW_MSG("Failed to load one of the API assemblies."); + } #if defined(TOOLS_ENABLED) bool tools_assemblies_loaded = _load_tools_assemblies(); @@ -1104,49 +785,6 @@ 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()) { - return corlib_assembly->get_class(p_raw_class); - } - - int32_t domain_id = mono_domain_get_id(mono_domain_get()); - HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - - for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { - GDMonoAssembly *assembly = E.value; - if (assembly->get_image() == image) { - GDMonoClass *klass = assembly->get_class(p_raw_class); - if (klass) { - return klass; - } - } - } - - return nullptr; -} - -GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName &p_name) { - GDMonoClass *klass = corlib_assembly->get_class(p_namespace, p_name); - if (klass) { - return klass; - } - - int32_t domain_id = mono_domain_get_id(mono_domain_get()); - HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - - for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { - GDMonoAssembly *assembly = E.value; - klass = assembly->get_class(p_namespace, p_name); - if (klass) { - return klass; - } - } - - return nullptr; -} - void GDMono::_domain_assemblies_cleanup(int32_t p_domain_id) { HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id]; |