int main(int argc, char* argv[]) { fs::path game_dir("C:\\my\\unity\\proj1\\proj1\\build\\1_Data"); fs::path managed_dir = game_dir / "Managed"; fs::path mono_dir = game_dir / "Mono"; fs::path dll_path = mono_dir / "_mono.dll"; HMODULE dll = LoadLibraryA(dll_path.string().c_str()); auto f = make_shared<mono_wrapper::functions_t>(mono_wrapper::load_mono_functions_from_dll(dll)); f->mono_set_dirs(managed_dir.string().c_str(), (game_dir / "Mono/etc").string().c_str()); { std::stringstream ss; ss << managed_dir.string() << ";" << mono_dir.string(); f->mono_set_assemblies_path(ss.str().c_str()); } MonoDomain* domain = f->mono_jit_init("My domain"); auto s = new_String(f, "Hello!"); auto s1 = s->ToUpper(); string s1_content = s1->to_utf8(); int32_t len = s->get_Length(); return 0; }
int main() { /* TODO: using abs paths just to test this shit. */ // Set path where managed assemblies live. mono_set_assemblies_path("C:\\Users\\Niko\\Source\\Repos\\SaNi\\vs2013\\sanimono\\SaNi\\bin\\Debug"); // Set Mono library and configuration paths. mono_set_dirs("C:\\Program Files (x86)\\Mono\\lib", "C:\\Program Files (x86)\\Mono\\etc"); // Our application assembly that contains // the code we are going to run. domain = mono_jit_init_version("SaNi", "v4.0.30319"); // Our domain in which the code will be // executed. MonoAssembly* assembly = mono_domain_assembly_open(domain, "C:\\Users\\Niko\\Source\\Repos\\SaNi\\vs2013\\sanimono\\SaNi\\bin\\Debug\\SaNi.exe"); if (!assembly) throw std::runtime_error("could not load the given Mono assembly"); mono_add_internal_call("SaNi.Utils::Print(string)", (void*)print); mono_add_internal_call("SaNi.Utils::GetString()", (void*)getString); const auto argc = 6; char* argv[argc] = { "HELLO", "WORLD", "FROM", "THE", "F*****G", "MONO" }; mono_jit_exec(domain, assembly, argc, argv); // Clean mono. mono_jit_cleanup(domain); return 0; }
int main (int argc, char* argv[]) { char **newargs; int i, k = 0; newargs = (char **) malloc (sizeof (char *) * (argc + 2 + count_mono_options_args ())); newargs [k++] = argv [0]; if (mono_options != NULL) { i = 0; while (mono_options[i] != NULL) newargs[k++] = mono_options[i++]; } newargs [k++] = image_name; for (i = 1; i < argc; i++) { newargs [k++] = argv [i]; } newargs [k] = NULL; if (config_dir != NULL && getenv ("MONO_CFG_DIR") == NULL) mono_set_dirs (getenv ("MONO_PATH"), config_dir); mono_mkbundle_init(); return mono_main (k, newargs); }
void main(int argc, char* argv[]) { mono_set_dirs("lib", ""); mono_config_parse(NULL); MonoDomain* domain = mono_jit_init("managed.exe"); if(!domain) { printf("Unable to initialize mono jit.\n"); return; } MonoAssembly* assembly = mono_domain_assembly_open(domain, "managed.exe"); if (!assembly) { printf("Unable to open assembly.\n"); return; } char* argvv[1] = { "managed" }; mono_jit_exec(domain, assembly, 1, argvv); mono_jit_cleanup(domain); return; }
const char* mono_get_config_dir (void) { if (mono_cfg_dir == NULL) mono_set_dirs (NULL, NULL); return mono_cfg_dir; }
void MonoRuntime::Load(std::string assemblyDir, std::string configDir, std::string traceLevel, std::string file) { if (isLoaded_) { return; } if (!assemblyDir.empty() && !configDir.empty()) { mono_set_dirs(assemblyDir.c_str(), configDir.c_str()); } #ifdef _WIN32 else { mono_set_dirs(PathUtil::GetLibDirectory().c_str(), PathUtil::GetConfigDirectory().c_str()); } #endif mono_trace_set_level_string(traceLevel.c_str()); MonoDomain *dom = mono_jit_init(file.c_str()); isLoaded_ = true; }
int main (int argc, char* argv[]) { char **newargs; int i, k = 0; #ifdef _WIN32 /* CommandLineToArgvW() might return a different argc than the * one passed to main(), so let it overwrite that, as we won't * use argv[] on Windows anyway. */ wchar_t **wargv = CommandLineToArgvW (GetCommandLineW (), &argc); #endif newargs = (char **) malloc (sizeof (char *) * (argc + 2) + count_mono_options_args ()); #ifdef _WIN32 newargs [k++] = g_utf16_to_utf8 (wargv [0], -1, NULL, NULL, NULL); #else newargs [k++] = argv [0]; #endif if (mono_options != NULL) { i = 0; while (mono_options[i] != NULL) newargs[k++] = mono_options[i++]; } newargs [k++] = image_name; for (i = 1; i < argc; i++) { #ifdef _WIN32 newargs [k++] = g_utf16_to_utf8 (wargv [i], -1, NULL, NULL, NULL); #else newargs [k++] = argv [i]; #endif } #ifdef _WIN32 LocalFree (wargv); #endif newargs [k] = NULL; if (config_dir != NULL && getenv ("MONO_CFG_DIR") == NULL) mono_set_dirs (getenv ("MONO_PATH"), config_dir); mono_mkbundle_init(); return mono_main (k, newargs); }
void Application::Init() { assemblyDir = "Managed"; std::vector<std::string> monoPaths; // root of the mono dir std::string monoDir = File::BuildRootedPath("mono"); std::string libmonoDir = File::BuildPath(monoDir, "lib"); std::string etcmonoDir = File::BuildPath(monoDir, "etc"); // where we find user code std::string dllDir = File::BuildRootedPath(assemblyDir); mono_set_dirs(libmonoDir.c_str(), etcmonoDir.c_str()); // save it for later, although it's not used it can be useful // to scan for new assemblies monoPaths.push_back(dllDir.c_str()); InitializeMono(); }
static HRESULT load_mono(LPCWSTR mono_path) { static const WCHAR lib[] = {'\\','l','i','b',0}; static const WCHAR etc[] = {'\\','e','t','c',0}; WCHAR mono_dll_path[MAX_PATH+16]; WCHAR mono_lib_path[MAX_PATH+4], mono_etc_path[MAX_PATH+4]; char mono_lib_path_a[MAX_PATH], mono_etc_path_a[MAX_PATH]; int trace_size; char trace_setting[256]; int verbose_size; char verbose_setting[256]; if (is_mono_shutdown) { ERR("Cannot load Mono after it has been shut down.\n"); return E_FAIL; } if (!mono_handle) { strcpyW(mono_lib_path, mono_path); strcatW(mono_lib_path, lib); WideCharToMultiByte(CP_UTF8, 0, mono_lib_path, -1, mono_lib_path_a, MAX_PATH, NULL, NULL); strcpyW(mono_etc_path, mono_path); strcatW(mono_etc_path, etc); WideCharToMultiByte(CP_UTF8, 0, mono_etc_path, -1, mono_etc_path_a, MAX_PATH, NULL, NULL); if (!find_mono_dll(mono_path, mono_dll_path)) goto fail; mono_handle = LoadLibraryW(mono_dll_path); if (!mono_handle) goto fail; #define LOAD_MONO_FUNCTION(x) do { \ x = (void*)GetProcAddress(mono_handle, #x); \ if (!x) { \ goto fail; \ } \ } while (0); LOAD_MONO_FUNCTION(mono_assembly_get_image); LOAD_MONO_FUNCTION(mono_assembly_load_from); LOAD_MONO_FUNCTION(mono_assembly_open); LOAD_MONO_FUNCTION(mono_config_parse); LOAD_MONO_FUNCTION(mono_class_from_mono_type); LOAD_MONO_FUNCTION(mono_class_from_name); LOAD_MONO_FUNCTION(mono_class_get_method_from_name); LOAD_MONO_FUNCTION(mono_domain_assembly_open); LOAD_MONO_FUNCTION(mono_domain_get); LOAD_MONO_FUNCTION(mono_domain_get_by_id); LOAD_MONO_FUNCTION(mono_domain_set); LOAD_MONO_FUNCTION(mono_domain_set_config); LOAD_MONO_FUNCTION(mono_free); LOAD_MONO_FUNCTION(mono_image_open); LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook); LOAD_MONO_FUNCTION(mono_jit_exec); LOAD_MONO_FUNCTION(mono_jit_init_version); LOAD_MONO_FUNCTION(mono_jit_set_trace_options); LOAD_MONO_FUNCTION(mono_marshal_get_vtfixup_ftnptr); LOAD_MONO_FUNCTION(mono_object_get_domain); LOAD_MONO_FUNCTION(mono_object_get_virtual_method); LOAD_MONO_FUNCTION(mono_object_new); LOAD_MONO_FUNCTION(mono_object_unbox); LOAD_MONO_FUNCTION(mono_profiler_install); LOAD_MONO_FUNCTION(mono_reflection_type_from_name); LOAD_MONO_FUNCTION(mono_runtime_invoke); LOAD_MONO_FUNCTION(mono_runtime_object_init); LOAD_MONO_FUNCTION(mono_runtime_quit); LOAD_MONO_FUNCTION(mono_set_dirs); LOAD_MONO_FUNCTION(mono_set_verbose_level); LOAD_MONO_FUNCTION(mono_stringify_assembly_name); LOAD_MONO_FUNCTION(mono_string_new); LOAD_MONO_FUNCTION(mono_thread_attach); LOAD_MONO_FUNCTION(mono_thread_manage); LOAD_MONO_FUNCTION(mono_trace_set_assembly); #undef LOAD_MONO_FUNCTION #define LOAD_OPT_MONO_FUNCTION(x, default) do { \ x = (void*)GetProcAddress(mono_handle, #x); \ if (!x) { \ x = default; \ } \ } while (0); LOAD_OPT_MONO_FUNCTION(mono_image_open_from_module_handle, image_open_module_handle_dummy); LOAD_OPT_MONO_FUNCTION(mono_trace_set_print_handler, set_print_handler_dummy); LOAD_OPT_MONO_FUNCTION(mono_trace_set_printerr_handler, set_print_handler_dummy); #undef LOAD_OPT_MONO_FUNCTION mono_profiler_install(NULL, mono_shutdown_callback_fn); mono_trace_set_print_handler(mono_print_handler_fn); mono_trace_set_printerr_handler(mono_print_handler_fn); mono_set_dirs(mono_lib_path_a, mono_etc_path_a); mono_config_parse(NULL); mono_install_assembly_preload_hook(mono_assembly_preload_hook_fn, NULL); trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting)); if (trace_size) { mono_jit_set_trace_options(trace_setting); } verbose_size = GetEnvironmentVariableA("WINE_MONO_VERBOSE", verbose_setting, sizeof(verbose_setting)); if (verbose_size) { mono_set_verbose_level(verbose_setting[0] - '0'); } } return S_OK; fail: ERR("Could not load Mono into this process\n"); FreeLibrary(mono_handle); mono_handle = NULL; return E_FAIL; }
CScriptSystem::CScriptSystem(IGameFramework *pGameFramework) : m_pRootDomain(nullptr) , m_pCryBraryAssembly(nullptr) , m_pPdb2MdbAssembly(nullptr) , m_pScriptManager(nullptr) , m_pScriptDomain(nullptr) , m_bReloading(false) , m_bDetectedChanges(false) , m_bQuitting(false) , m_pConverter(nullptr) , m_bFirstReload(true) , m_pGameFramework(pGameFramework) { CryLogAlways("Initializing Mono Script System"); g_pThis = this; m_pCVars = new SCVars(); g_pMonoCVars = m_pCVars; // We should look into storing mono binaries, configuration as well as scripts via CryPak. mono_set_dirs(PathUtils::GetMonoLibPath(), PathUtils::GetMonoConfigPath()); #ifndef _RELEASE // Enable Mono signal handling // Makes sure that Mono sends back exceptions it tries to handle, for CE crash handling. mono_set_signal_chaining(true); #endif string monoCmdOptions = ""; if(auto *pArg = gEnv->pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "monoArgs")) monoCmdOptions.append(pArg->GetValue()); // Commandline switch -DEBUG makes the process connect to the debugging server. Warning: Failure to connect to a debugging server WILL result in a crash. // This is currently a WIP feature which requires custom MonoDevelop extensions and other irritating things. const ICmdLineArg* arg = gEnv->pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "DEBUG"); if (arg != nullptr) monoCmdOptions.append("--debugger-agent=transport=dt_socket,address=127.0.0.1:65432,embedding=1"); #ifndef _RELEASE else if(g_pMonoCVars->mono_softBreakpoints) // Soft breakpoints not compatible with debugging server { CryLogAlways(" [Performance Warning] Mono soft breakpoints are enabled!"); // Prevents managed null reference exceptions causing crashes in unmanaged code // See: https://bugzilla.xamarin.com/show_bug.cgi?id=5963 monoCmdOptions.append("--soft-breakpoints"); } #endif char *options = new char[monoCmdOptions.size() + 1]; strcpy(options, monoCmdOptions.c_str()); // Note: iPhone requires AOT compilation, this can be enforced via mono options. TODO: Get Crytek to add CryMobile support to the Free SDK. mono_jit_parse_options(1, &options); #ifndef _RELEASE // Required for mdb's to load for detailed stack traces etc. mono_debug_init(MONO_DEBUG_FORMAT_MONO); #endif m_pConverter = new CConverter(); if(!CompleteInit()) { CryLogAlways("CryMono initialization failed!"); return; } RegisterSecondaryBindings(); pGameFramework->RegisterListener(this, "CryMono", FRAMEWORKLISTENERPRIORITY_GAME); gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(&g_systemEventListener_CryMono); if(IFileChangeMonitor *pFileChangeMonitor = gEnv->pFileChangeMonitor) pFileChangeMonitor->RegisterListener(this, "scripts\\"); CryModuleMemoryInfo memInfo; CryModuleGetMemoryInfo(&memInfo); IMonoClass *pCryStats = m_pCryBraryAssembly->GetClass("CryStats", "CryEngine.Utilities"); IMonoObject *pMemoryUsage = *pCryStats->GetPropertyValue(NULL, "MemoryUsage"); CryLogAlways(" Initializing CryMono done, MemUsage=%iKb", (memInfo.allocated + pMemoryUsage->Unbox<long>()) / 1024); pMemoryUsage->Release(); }
int main (int argc, char* argv[]) { char **newargs; int i, k = 0; #ifdef _WIN32 /* CommandLineToArgvW() might return a different argc than the * one passed to main(), so let it overwrite that, as we won't * use argv[] on Windows anyway. */ wchar_t **wargv = CommandLineToArgvW (GetCommandLineW (), &argc); #endif newargs = (char **) malloc (sizeof (char *) * (argc + 2) + count_mono_options_args ()); #ifdef _WIN32 newargs [k++] = g_utf16_to_utf8 (wargv [0], -1, NULL, NULL, NULL); #else newargs [k++] = argv [0]; #endif if (mono_options != NULL) { i = 0; while (mono_options[i] != NULL) newargs[k++] = mono_options[i++]; } BrInitError err = 0; if (br_init(&err) == 1) { char *exedir = br_find_exe_dir(NULL); if (exedir) { setenv("MONO_PATH",exedir,1); mono_set_dirs(exedir, exedir); chdir(exedir); free(exedir); } } else { switch (err) { case BR_INIT_ERROR_NOMEM: printf("Could not allocate enough memory\n"); break; case BR_INIT_ERROR_OPEN_MAPS: case BR_INIT_ERROR_READ_MAPS: case BR_INIT_ERROR_INVALID_MAPS: printf("Couldn't access /proc/self/maps!\n"); break; case BR_INIT_ERROR_DISABLED: printf("BinReloc disabled!!\n"); break; } return 1; } // Calculate image_name char *image_name; char *exe = br_find_exe(NULL); char *pos = strrchr(exe, '/'); if (pos != NULL) { image_name = strdup(pos+1); pos = strstr(image_name,".bin."); if (pos != NULL) { strcpy(pos, ".exe"); } } free(exe); newargs [k++] = image_name; for (i = 1; i < argc; i++) { #ifdef _WIN32 newargs [k++] = g_utf16_to_utf8 (wargv [i], -1, NULL, NULL, NULL); #else newargs [k++] = argv [i]; #endif } #ifdef _WIN32 LocalFree (wargv); #endif newargs [k] = NULL; return mono_main (k, newargs); }
CScriptSystem::CScriptSystem() : m_pRootDomain(nullptr) , m_pCryBraryAssembly(nullptr) , m_pPdb2MdbAssembly(nullptr) , m_pScriptManager(nullptr) , m_pScriptDomain(nullptr) , m_bReloading(false) , m_bDetectedChanges(false) , m_bQuitting(false) , m_pConverter(nullptr) { CryLogAlways("Initializing Mono Script System"); #ifndef PLUGIN_SDK gEnv->pMonoScriptSystem = this; #endif; g_pScriptSystem = this; m_pCVars = new SCVars(); g_pMonoCVars = m_pCVars; // We should look into storing mono binaries, configuration as well as scripts via CryPak. mono_set_dirs(PathUtils::GetMonoLibPath(), PathUtils::GetMonoConfigPath()); #ifndef _RELEASE // Enable Mono signal handling // Makes sure that Mono sends back exceptions it tries to handle, for CE crash handling. mono_set_signal_chaining(true); #endif string monoCmdOptions = ""; if(auto *pArg = gEnv->pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "monoArgs")) monoCmdOptions.append(pArg->GetValue()); // Commandline switch -DEBUG makes the process connect to the debugging server. Warning: Failure to connect to a debugging server WILL result in a crash. // This is currently a WIP feature which requires custom MonoDevelop extensions and other irritating things. const ICmdLineArg* arg = gEnv->pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "DEBUG"); if (arg != nullptr) monoCmdOptions.append("--debugger-agent=transport=dt_socket,address=127.0.0.1:65432,embedding=1"); #ifndef _RELEASE else if(g_pMonoCVars->mono_softBreakpoints) // Soft breakpoints not compatible with debugging server { CryLogAlways(" [Performance Warning] Mono soft breakpoints are enabled!"); // Prevents managed null reference exceptions causing crashes in unmanaged code // See: https://bugzilla.xamarin.com/show_bug.cgi?id=5963 monoCmdOptions.append("--soft-breakpoints"); } #endif char *options = new char[monoCmdOptions.size() + 1]; strcpy(options, monoCmdOptions.c_str()); // Note: iPhone requires AOT compilation, this can be enforced via mono options. TODO: Get Crytek to add CryMobile support to the Free SDK. mono_jit_parse_options(1, &options); #ifndef _RELEASE // Required for mdb's to load for detailed stack traces etc. mono_debug_init(MONO_DEBUG_FORMAT_MONO); #endif m_pConverter = new CConverter(); if(!CompleteInit()) return; if(IFileChangeMonitor *pFileChangeMonitor = gEnv->pFileChangeMonitor) pFileChangeMonitor->RegisterListener(this, "scripts\\"); }
void GDMono::initialize() { ERR_FAIL_NULL(Engine::get_singleton()); print_verbose("Mono: Initializing module..."); #ifdef DEBUG_METHODS_ENABLED _initialize_and_check_api_hashes(); #endif GDMonoLog::get_singleton()->initialize(); #ifdef MONO_PRINT_HANDLER_ENABLED mono_trace_set_print_handler(gdmono_MonoPrintCallback); mono_trace_set_printerr_handler(gdmono_MonoPrintCallback); #endif #ifdef WINDOWS_ENABLED mono_reg_info = MonoRegUtils::find_mono(); CharString assembly_dir; CharString config_dir; if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) { assembly_dir = mono_reg_info.assembly_dir.utf8(); } if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) { config_dir = mono_reg_info.config_dir.utf8(); } mono_set_dirs(assembly_dir.length() ? assembly_dir.get_data() : NULL, config_dir.length() ? config_dir.get_data() : NULL); #elif OSX_ENABLED mono_set_dirs(NULL, NULL); { const char *assembly_rootdir = mono_assembly_getrootdir(); const char *config_dir = mono_get_config_dir(); if (!assembly_rootdir || !config_dir || !DirAccess::exists(assembly_rootdir) || !DirAccess::exists(config_dir)) { Vector<const char *> locations; locations.push_back("/Library/Frameworks/Mono.framework/Versions/Current/"); locations.push_back("/usr/local/var/homebrew/linked/mono/"); for (int i = 0; i < locations.size(); i++) { String hint_assembly_rootdir = path_join(locations[i], "lib"); String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll"); String hint_config_dir = path_join(locations[i], "etc"); if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) { mono_set_dirs(hint_assembly_rootdir.utf8().get_data(), hint_config_dir.utf8().get_data()); break; } } } } #else mono_set_dirs(NULL, NULL); #endif GDMonoAssembly::initialize(); #ifdef DEBUG_ENABLED gdmono_debug_init(); #endif mono_config_parse(NULL); mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL); root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319"); ERR_EXPLAIN("Mono: Failed to initialize runtime"); ERR_FAIL_NULL(root_domain); GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread()); setup_runtime_main_args(); // Required for System.Environment.GetCommandLineArgs runtime_initialized = true; print_verbose("Mono: Runtime initialized"); // mscorlib assembly MUST be present at initialization ERR_EXPLAIN("Mono: Failed to load mscorlib assembly"); ERR_FAIL_COND(!_load_corlib_assembly()); #ifdef TOOLS_ENABLED // The tools domain must be loaded here, before the scripts domain. // Otherwise domain unload on the scripts domain will hang indefinitely. ERR_EXPLAIN("Mono: Failed to load tools domain"); ERR_FAIL_COND(_load_tools_domain() != OK); // TODO move to editor init callback, and do it lazily when required before editor init (e.g.: bindings generation) ERR_EXPLAIN("Mono: Failed to load Editor Tools assembly"); ERR_FAIL_COND(!_load_editor_tools_assembly()); #endif ERR_EXPLAIN("Mono: Failed to load scripts domain"); ERR_FAIL_COND(_load_scripts_domain() != OK); #ifdef DEBUG_ENABLED bool debugger_attached = _wait_for_debugger_msecs(500); if (!debugger_attached && OS::get_singleton()->is_stdout_verbose()) print_error("Mono: Debugger wait timeout"); #endif _register_internal_calls(); // The following assemblies are not required at initialization #ifdef MONO_GLUE_ENABLED if (_load_api_assemblies()) { if (!core_api_assembly_out_of_sync && !editor_api_assembly_out_of_sync && GDMonoUtils::mono_cache.godot_api_cache_updated) { // Everything is fine with the api assemblies, load the project assembly _load_project_assembly(); } else { #ifdef TOOLS_ENABLED // The assembly was successfully loaded, but the full api could not be cached. // This is most likely an outdated assembly loaded because of an invalid version in the metadata, // so we invalidate the version in the metadata and unload the script domain. if (core_api_assembly_out_of_sync) { ERR_PRINT("The loaded Core API assembly is out of sync"); metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed"); metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); } if (editor_api_assembly_out_of_sync) { ERR_PRINT("The loaded Editor API assembly is out of sync"); metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true); } print_line("Mono: Proceeding to unload scripts domain because of invalid API assemblies."); Error err = _unload_scripts_domain(); if (err != OK) { WARN_PRINT("Mono: Failed to unload scripts domain"); } #else ERR_PRINT("The loaded API assembly is invalid"); CRASH_NOW(); #endif } } #else print_verbose("Mono: Glue disabled, ignoring script assemblies."); #endif print_verbose("Mono: INITIALIZED"); }
static void InitMono() { std::string citizenClrPath = MakeRelativeNarrowPath("citizen/clr2/lib/"); std::string citizenCfgPath = MakeRelativeNarrowPath("citizen/clr2/cfg/"); mono_set_dirs(citizenClrPath.c_str(), citizenCfgPath.c_str()); #ifdef _WIN32 std::wstring citizenClrLibPath = MakeRelativeCitPath(L"citizen/clr2/lib/mono/4.5/"); SetEnvironmentVariable(L"MONO_PATH", citizenClrLibPath.c_str()); mono_set_crash_chaining(true); #else std::string citizenClrLibPath = MakeRelativeNarrowPath("citizen/clr2/lib/mono/4.5/"); putenv(const_cast<char*>(va("MONO_PATH=%s", citizenClrLibPath))); #endif mono_assembly_setrootdir(citizenClrPath.c_str()); putenv("MONO_DEBUG=casts"); #ifndef IS_FXSERVER mono_security_enable_core_clr(); mono_security_core_clr_set_options((MonoSecurityCoreCLROptions)(MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_DELEGATE | MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION)); mono_security_set_core_clr_platform_callback(CoreClrCallback); #endif char* args[1]; #ifdef _WIN32 args[0] = "--soft-breakpoints"; #else args[0] = "--use-fallback-tls"; #endif mono_jit_parse_options(1, args); mono_debug_init(MONO_DEBUG_FORMAT_MONO); g_rootDomain = mono_jit_init_version("Citizen", "v4.0.30319"); mono_domain_set_config(g_rootDomain, ".", "cfx.config"); mono_install_unhandled_exception_hook([] (MonoObject* exc, void*) { OutputExceptionDetails(exc); }, nullptr); mono_set_crash_chaining(true); mono_add_internal_call("CitizenFX.Core.GameInterface::PrintLog", reinterpret_cast<void*>(GI_PrintLogCall)); mono_add_internal_call("CitizenFX.Core.GameInterface::fwFree", reinterpret_cast<void*>(fwFree)); std::string platformPath = MakeRelativeNarrowPath("citizen/clr2/lib/mono/4.5/CitizenFX.Core.dll"); auto scriptManagerAssembly = mono_domain_assembly_open(g_rootDomain, platformPath.c_str()); if (!scriptManagerAssembly) { FatalError("Could not load CitizenFX.Core.dll.\n"); } auto scriptManagerImage = mono_assembly_get_image(scriptManagerAssembly); bool methodSearchSuccess = true; MonoMethodDesc* description; #define method_search(name, method) description = mono_method_desc_new(name, 1); \ method = mono_method_desc_search_in_image(description, scriptManagerImage); \ mono_method_desc_free(description); \ methodSearchSuccess = methodSearchSuccess && method != NULL MonoMethod* rtInitMethod; method_search("CitizenFX.Core.RuntimeManager:Initialize", rtInitMethod); method_search("CitizenFX.Core.RuntimeManager:GetImplementedClasses", g_getImplementsMethod); method_search("CitizenFX.Core.RuntimeManager:CreateObjectInstance", g_createObjectMethod); if (!methodSearchSuccess) { FatalError("Couldn't find one or more CitizenFX.Core methods.\n"); } MonoObject* exc = nullptr; mono_runtime_invoke(rtInitMethod, nullptr, nullptr, &exc); if (exc) { OutputExceptionDetails(exc); return; } }
void GDMono::initialize() { ERR_FAIL_NULL(Engine::get_singleton()); OS::get_singleton()->print("Mono: Initializing module...\n"); #ifdef DEBUG_METHODS_ENABLED _initialize_and_check_api_hashes(); #endif GDMonoLog::get_singleton()->initialize(); #ifdef MONO_PRINT_HANDLER_ENABLED mono_trace_set_print_handler(gdmono_MonoPrintCallback); mono_trace_set_printerr_handler(gdmono_MonoPrintCallback); #endif #ifdef WINDOWS_ENABLED mono_reg_info = MonoRegUtils::find_mono(); CharString assembly_dir; CharString config_dir; if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) { assembly_dir = mono_reg_info.assembly_dir.utf8(); } if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) { config_dir = mono_reg_info.config_dir.utf8(); } mono_set_dirs(assembly_dir.length() ? assembly_dir.get_data() : NULL, config_dir.length() ? config_dir.get_data() : NULL); #else mono_set_dirs(NULL, NULL); #endif GDMonoAssembly::initialize(); #ifdef DEBUG_ENABLED gdmono_debug_init(); #endif mono_config_parse(NULL); root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319"); ERR_EXPLAIN("Mono: Failed to initialize runtime"); ERR_FAIL_NULL(root_domain); GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread()); runtime_initialized = true; OS::get_singleton()->print("Mono: Runtime initialized\n"); // mscorlib assembly MUST be present at initialization ERR_EXPLAIN("Mono: Failed to load mscorlib assembly"); ERR_FAIL_COND(!_load_corlib_assembly()); #ifdef TOOLS_ENABLED // The tools domain must be loaded here, before the scripts domain. // Otherwise domain unload on the scripts domain will hang indefinitely. ERR_EXPLAIN("Mono: Failed to load tools domain"); ERR_FAIL_COND(_load_tools_domain() != OK); // TODO move to editor init callback, and do it lazily when required before editor init (e.g.: bindings generation) ERR_EXPLAIN("Mono: Failed to load Editor Tools assembly"); ERR_FAIL_COND(!_load_editor_tools_assembly()); #endif ERR_EXPLAIN("Mono: Failed to load scripts domain"); ERR_FAIL_COND(_load_scripts_domain() != OK); #ifdef DEBUG_ENABLED bool debugger_attached = _wait_for_debugger_msecs(500); if (!debugger_attached && OS::get_singleton()->is_stdout_verbose()) OS::get_singleton()->printerr("Mono: Debugger wait timeout\n"); #endif _register_internal_calls(); // The following assemblies are not required at initialization _load_all_script_assemblies(); mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL); OS::get_singleton()->print("Mono: INITIALIZED\n"); }