diff options
author | Ignacio Etcheverry <neikeq@users.noreply.github.com> | 2018-08-22 00:27:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-22 00:27:35 +0200 |
commit | 5df91099c74889d48d05de9ad677f24ac71a0d48 (patch) | |
tree | 5c66e3dddd88e5d7c5100c1331c36118762ebad2 /modules/mono/mono_gd | |
parent | 27731a86d2003e0b98a217d191dc7e180ddf043b (diff) | |
parent | ce4451b45ffe6f8a73090e26faa0d9ceaaa61fed (diff) |
Merge pull request #18502 from space-wizards/18-04-29-assembly-load-hook
assembly_load_hook fallback for registering GDMonoAssemblies.
Diffstat (limited to 'modules/mono/mono_gd')
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.cpp | 47 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.h | 2 |
2 files changed, 45 insertions, 4 deletions
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 9d3bee2176..57797598e1 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -44,6 +44,17 @@ bool GDMonoAssembly::no_search = false; Vector<String> GDMonoAssembly::search_dirs; +void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) { + // If our search and preload hooks fail to load the assembly themselves, the mono runtime still might. + // Just do Assembly.LoadFrom("/Full/Path/On/Disk.dll"); + // In this case, we wouldn't have the assembly known in GDMono, which causes crashes + // if any class inside the assembly is looked up by Godot. + // And causing a lookup like that is as easy as throwing an exception defined in it... + // No, we can't make the assembly load hooks smart enough because they get passed a MonoAssemblyName* only, + // not the disk path passed to say Assembly.LoadFrom(). + _wrap_mono_assembly(assembly); +} + MonoAssembly *GDMonoAssembly::assembly_search_hook(MonoAssemblyName *aname, void *user_data) { return GDMonoAssembly::_search_hook(aname, user_data, false); } @@ -138,16 +149,21 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse } } + if (no_search) + return NULL; + + no_search = true; + String name = mono_assembly_name_get_name(aname); bool has_extension = name.ends_with(".dll"); + GDMonoAssembly *res = NULL; if (has_extension ? name == "mscorlib.dll" : name == "mscorlib") { GDMonoAssembly **stored_assembly = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); if (stored_assembly) return (*stored_assembly)->get_assembly(); String path; - GDMonoAssembly *res = NULL; for (int i = 0; i < search_dirs.size(); i++) { const String &search_dir = search_dirs[i]; @@ -168,11 +184,11 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse } } } - - return res ? res->get_assembly() : NULL; } - return NULL; + no_search = false; + + return res ? res->get_assembly() : NULL; } GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) { @@ -192,12 +208,35 @@ GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const return assembly; } +void GDMonoAssembly::_wrap_mono_assembly(MonoAssembly *assembly) { + String p_name = mono_assembly_name_get_name(mono_assembly_get_name(assembly)); + GDMonoAssembly **existingassembly = GDMono::get_singleton()->get_loaded_assembly(p_name); + + if (no_search || existingassembly != NULL) { + // Not sure whether the existingassembly check matters + // since no_search handles it in most cases? + // Can't hurt. + return; + } + + MonoImage *image = mono_assembly_get_image(assembly); + mono_image_addref(image); + + GDMonoAssembly *gdassembly = memnew(GDMonoAssembly(p_name, mono_image_get_filename(image))); + gdassembly->assembly = assembly; + gdassembly->loaded = true; + gdassembly->image = image; + MonoDomain *domain = mono_domain_get(); + GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, gdassembly); +} + void GDMonoAssembly::initialize() { mono_install_assembly_search_hook(&assembly_search_hook, NULL); mono_install_assembly_refonly_search_hook(&assembly_refonly_search_hook, NULL); mono_install_assembly_preload_hook(&assembly_preload_hook, NULL); mono_install_assembly_refonly_preload_hook(&assembly_refonly_preload_hook, NULL); + mono_install_assembly_load_hook(&assembly_load_hook, NULL); } Error GDMonoAssembly::load(bool p_refonly) { diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 5cf744a5a2..e8f2be62f8 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -91,6 +91,7 @@ class GDMonoAssembly { static bool no_search; static Vector<String> search_dirs; + static void assembly_load_hook(MonoAssembly *assembly, void *user_data); static MonoAssembly *assembly_search_hook(MonoAssemblyName *aname, void *user_data); static MonoAssembly *assembly_refonly_search_hook(MonoAssemblyName *aname, void *user_data); static MonoAssembly *assembly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); @@ -100,6 +101,7 @@ class GDMonoAssembly { static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly); static GDMonoAssembly *_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly); + static void _wrap_mono_assembly(MonoAssembly *assembly); friend class GDMono; static void initialize(); |