summaryrefslogtreecommitdiff
path: root/modules/mono/mono_gd
diff options
context:
space:
mode:
authorIgnacio Etcheverry <neikeq@users.noreply.github.com>2018-08-22 00:27:35 +0200
committerGitHub <noreply@github.com>2018-08-22 00:27:35 +0200
commit5df91099c74889d48d05de9ad677f24ac71a0d48 (patch)
tree5c66e3dddd88e5d7c5100c1331c36118762ebad2 /modules/mono/mono_gd
parent27731a86d2003e0b98a217d191dc7e180ddf043b (diff)
parentce4451b45ffe6f8a73090e26faa0d9ceaaa61fed (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.cpp47
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h2
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();