Merge pull request #11900 from neikeq/a
Fix assembly load hooks and sizeof wrong type
This commit is contained in:
commit
5a49106ff4
5 changed files with 89 additions and 58 deletions
|
@ -59,7 +59,7 @@ String _find_build_engine_on_unix(const String &p_name) {
|
||||||
"/opt/novell/mono/bin/"
|
"/opt/novell/mono/bin/"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(locations) / sizeof(char); i++) {
|
for (int i = 0; i < sizeof(locations) / sizeof(const char *); i++) {
|
||||||
String location = locations[i];
|
String location = locations[i];
|
||||||
|
|
||||||
if (FileAccess::exists(location + p_name)) {
|
if (FileAccess::exists(location + p_name)) {
|
||||||
|
|
|
@ -266,6 +266,13 @@ void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) {
|
||||||
assemblies[p_domain_id][p_assembly->get_name()] = p_assembly;
|
assemblies[p_domain_id][p_assembly->get_name()] = p_assembly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) {
|
||||||
|
|
||||||
|
MonoDomain *domain = mono_domain_get();
|
||||||
|
uint32_t domain_id = domain ? mono_domain_get_id(domain) : 0;
|
||||||
|
return assemblies[domain_id].getptr(p_name);
|
||||||
|
}
|
||||||
|
|
||||||
bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
|
bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
|
||||||
|
|
||||||
CRASH_COND(!r_assembly);
|
CRASH_COND(!r_assembly);
|
||||||
|
@ -285,27 +292,11 @@ bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
|
||||||
|
|
||||||
GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name);
|
GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name);
|
||||||
|
|
||||||
if (stored_assembly) {
|
ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false);
|
||||||
// Loaded by our preload hook (status is not initialized when returning from a preload hook)
|
ERR_FAIL_COND_V(stored_assembly == NULL, false);
|
||||||
ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false);
|
|
||||||
*r_assembly = *stored_assembly;
|
|
||||||
} else {
|
|
||||||
ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false);
|
|
||||||
|
|
||||||
MonoImage *assembly_image = mono_assembly_get_image(assembly);
|
ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false);
|
||||||
ERR_FAIL_NULL_V(assembly_image, false);
|
*r_assembly = *stored_assembly;
|
||||||
|
|
||||||
const char *path = mono_image_get_filename(assembly_image);
|
|
||||||
|
|
||||||
*r_assembly = memnew(GDMonoAssembly(p_name, path));
|
|
||||||
Error error = (*r_assembly)->wrapper_for_image(assembly_image);
|
|
||||||
|
|
||||||
if (error != OK) {
|
|
||||||
memdelete(*r_assembly);
|
|
||||||
*r_assembly = NULL;
|
|
||||||
ERR_FAIL_V(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OS::get_singleton()->is_stdout_verbose())
|
if (OS::get_singleton()->is_stdout_verbose())
|
||||||
OS::get_singleton()->print(String("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8());
|
OS::get_singleton()->print(String("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8());
|
||||||
|
|
|
@ -122,7 +122,9 @@ public:
|
||||||
|
|
||||||
static GDMono *get_singleton() { return singleton; }
|
static GDMono *get_singleton() { return singleton; }
|
||||||
|
|
||||||
|
// 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(uint32_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; }
|
_FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized; }
|
||||||
_FORCE_INLINE_ bool is_finalizing_scripts_domain() const { return finalizing_scripts_domain; }
|
_FORCE_INLINE_ bool is_finalizing_scripts_domain() const { return finalizing_scripts_domain; }
|
||||||
|
|
|
@ -39,28 +39,61 @@
|
||||||
#include "../godotsharp_dirs.h"
|
#include "../godotsharp_dirs.h"
|
||||||
#include "gd_mono_class.h"
|
#include "gd_mono_class.h"
|
||||||
|
|
||||||
MonoAssembly *gdmono_load_assembly_from(const String &p_name, const String &p_path) {
|
bool GDMonoAssembly::no_search = false;
|
||||||
|
Vector<String> GDMonoAssembly::search_dirs;
|
||||||
|
|
||||||
MonoDomain *domain = mono_domain_get();
|
MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data) {
|
||||||
|
|
||||||
GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path));
|
|
||||||
Error err = assembly->load(domain);
|
|
||||||
ERR_FAIL_COND_V(err != OK, NULL);
|
|
||||||
|
|
||||||
GDMono::get_singleton()->add_assembly(mono_domain_get_id(domain), assembly);
|
|
||||||
|
|
||||||
return assembly->get_assembly();
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assemblies_path, void *user_data) {
|
|
||||||
|
|
||||||
(void)user_data; // UNUSED
|
(void)user_data; // UNUSED
|
||||||
|
|
||||||
MonoAssembly *assembly_loaded = mono_assembly_loaded(aname);
|
String name = mono_assembly_name_get_name(aname);
|
||||||
if (assembly_loaded) // Already loaded
|
|
||||||
return assembly_loaded;
|
|
||||||
|
|
||||||
static Vector<String> search_dirs;
|
if (no_search)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
no_search = true; // Avoid the recursion madness
|
||||||
|
|
||||||
|
GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(name.get_basename());
|
||||||
|
if (loaded_asm)
|
||||||
|
return (*loaded_asm)->get_assembly();
|
||||||
|
|
||||||
|
bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");
|
||||||
|
|
||||||
|
String path;
|
||||||
|
MonoAssembly *res = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < search_dirs.size(); i++) {
|
||||||
|
const String &search_dir = search_dirs[i];
|
||||||
|
|
||||||
|
if (has_extension) {
|
||||||
|
path = search_dir.plus_file(name);
|
||||||
|
if (FileAccess::exists(path)) {
|
||||||
|
res = _load_assembly_from(name.get_basename(), path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
path = search_dir.plus_file(name + ".dll");
|
||||||
|
if (FileAccess::exists(path)) {
|
||||||
|
res = _load_assembly_from(name, path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = search_dir.plus_file(name + ".exe");
|
||||||
|
if (FileAccess::exists(path)) {
|
||||||
|
res = _load_assembly_from(name, path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
no_search = false;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) {
|
||||||
|
|
||||||
|
(void)user_data; // UNUSED
|
||||||
|
|
||||||
if (search_dirs.empty()) {
|
if (search_dirs.empty()) {
|
||||||
search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
|
search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
|
||||||
|
@ -80,35 +113,32 @@ MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assembl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = mono_assembly_name_get_name(aname);
|
return NULL;
|
||||||
bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");
|
}
|
||||||
|
|
||||||
String path;
|
MonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path) {
|
||||||
|
|
||||||
for (int i = 0; i < search_dirs.size(); i++) {
|
GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path));
|
||||||
const String &search_dir = search_dirs[i];
|
|
||||||
|
|
||||||
if (has_extension) {
|
MonoDomain *domain = mono_domain_get();
|
||||||
path = search_dir.plus_file(name);
|
|
||||||
if (FileAccess::exists(path))
|
|
||||||
return gdmono_load_assembly_from(name.get_basename(), path);
|
|
||||||
} else {
|
|
||||||
path = search_dir.plus_file(name + ".dll");
|
|
||||||
if (FileAccess::exists(path))
|
|
||||||
return gdmono_load_assembly_from(name, path);
|
|
||||||
|
|
||||||
path = search_dir.plus_file(name + ".exe");
|
Error err = assembly->load(domain);
|
||||||
if (FileAccess::exists(path))
|
|
||||||
return gdmono_load_assembly_from(name, path);
|
if (err != OK) {
|
||||||
}
|
memdelete(assembly);
|
||||||
|
ERR_FAIL_V(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, assembly);
|
||||||
|
|
||||||
|
return assembly->get_assembly();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDMonoAssembly::initialize() {
|
void GDMonoAssembly::initialize() {
|
||||||
|
|
||||||
mono_install_assembly_preload_hook(&gdmono_MonoAssemblyPreLoad, NULL);
|
// TODO refonly as well?
|
||||||
|
mono_install_assembly_preload_hook(&GDMonoAssembly::_preload_hook, NULL);
|
||||||
|
mono_install_assembly_search_hook(&GDMonoAssembly::_search_hook, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error GDMonoAssembly::load(MonoDomain *p_domain) {
|
Error GDMonoAssembly::load(MonoDomain *p_domain) {
|
||||||
|
@ -153,7 +183,7 @@ no_pdb:
|
||||||
|
|
||||||
ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN);
|
ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN);
|
||||||
|
|
||||||
if (mono_image_get_entry_point(image)) {
|
if (p_domain && mono_image_get_entry_point(image)) {
|
||||||
// TODO should this be removed? do we want to call main? what other effects does this have?
|
// TODO should this be removed? do we want to call main? what other effects does this have?
|
||||||
mono_jit_exec(p_domain, assembly, 0, NULL);
|
mono_jit_exec(p_domain, assembly, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,14 @@ class GDMonoAssembly {
|
||||||
Vector<uint8_t> pdb_data;
|
Vector<uint8_t> pdb_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool no_search;
|
||||||
|
static Vector<String> search_dirs;
|
||||||
|
|
||||||
|
static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data);
|
||||||
|
static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
|
||||||
|
|
||||||
|
static MonoAssembly *_load_assembly_from(const String &p_name, const String &p_path);
|
||||||
|
|
||||||
friend class GDMono;
|
friend class GDMono;
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue