Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
const char* 
mono_get_config_dir (void)
{
	if (mono_cfg_dir == NULL)
		mono_set_dirs (NULL, NULL);

	return mono_cfg_dir;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
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();
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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();
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
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\\");
}
Ejemplo n.º 13
0
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");
}
Ejemplo n.º 14
0
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;
	}
}
Ejemplo n.º 15
0
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");
}