MonoObject *create_managed_from(const RID &p_from) { MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(RID)); ERR_FAIL_NULL_V(mono_object, NULL); // Construct mono_runtime_object_init(mono_object); CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from))); return mono_object; }
MonoArray* ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean neutral, MonoBoolean specific, MonoBoolean installed) { MonoArray *ret; MonoClass *klass; MonoCultureInfo *culture; MonoDomain *domain; const CultureInfoEntry *ci; gint i, len; gboolean is_neutral; domain = mono_domain_get (); len = 0; for (i = 0; i < NUM_CULTURE_ENTRIES; i++) { ci = &culture_entries [i]; is_neutral = ci->territory == 0; if ((neutral && is_neutral) || (specific && !is_neutral)) len++; } klass = mono_class_from_name (mono_get_corlib (), "System.Globalization", "CultureInfo"); /* The InvariantCulture is not in culture_entries */ /* We reserve the first slot in the array for it */ if (neutral) len++; ret = mono_array_new (domain, klass, len); if (len == 0) return ret; len = 0; if (neutral) mono_array_setref (ret, len++, NULL); for (i = 0; i < NUM_CULTURE_ENTRIES; i++) { ci = &culture_entries [i]; is_neutral = ci->territory == 0; if ((neutral && is_neutral) || (specific && !is_neutral)) { culture = (MonoCultureInfo *) mono_object_new (domain, klass); mono_runtime_object_init ((MonoObject *) culture); construct_culture (culture, ci); culture->use_user_override = TRUE; mono_array_setref (ret, len++, culture); } } return ret; }
mono::object CScriptClass::CreateInstance(IMonoArray *pConstructorParams) { CScriptDomain *pDomain = static_cast<CScriptDomain *>(GetAssembly()->GetDomain()); MonoObject *pInstance = mono_object_new(pDomain->GetMonoDomain(), (MonoClass *)m_pObject); if(pConstructorParams) InvokeArray((mono::object)pInstance, ".ctor", pConstructorParams); else mono_runtime_object_init(m_pObject); return (mono::object)pInstance; }
/** * mono_exception_from_token: * @image: the Mono image where to look for the class * @token: The type token of the class * * Creates an exception of the type given by @token. * * Returns: the initialized exception instance. */ MonoException * mono_exception_from_token (MonoImage *image, guint32 token) { MonoClass *klass; MonoObject *o; klass = mono_class_get (image, token); o = mono_object_new (mono_domain_get (), klass); g_assert (o != NULL); mono_runtime_object_init (o); return (MonoException *)o; }
/** * mono_exception_from_token: * @image: the Mono image where to look for the class * @token: The type token of the class * * Creates an exception of the type given by @token. * * Returns: the initialized exception instance. */ MonoException * mono_exception_from_token (MonoImage *image, guint32 token) { MonoError error; MonoClass *klass; MonoObject *o; klass = mono_class_get_checked (image, token, &error); g_assert (mono_error_ok (&error)); /* FIXME handle the error. */ o = mono_object_new_checked (mono_domain_get (), klass, &error); g_assert (o != NULL && mono_error_ok (&error)); /* FIXME don't swallow the error */ mono_runtime_object_init (o); return (MonoException *)o; }
/** * mono_exception_from_name_domain: * @domain: Domain where the return object will be created. * @image: the Mono image where to look for the class * @name_space: the namespace for the class * @name: class name * * Creates an exception object of the given namespace/name class on * the given domain. * * Returns: the initialized exception instance. */ MonoException * mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, const char* name_space, const char *name) { MonoClass *klass; MonoObject *o; MonoDomain *caller_domain = mono_domain_get (); klass = mono_class_from_name (image, name_space, name); o = mono_object_new (domain, klass); g_assert (o != NULL); if (domain != caller_domain) mono_domain_set_internal (domain); mono_runtime_object_init (o); if (domain != caller_domain) mono_domain_set_internal (caller_domain); return (MonoException *)o; }
MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) { String object_type = p_object->get_class_name(); if (object_type[0] == '_') object_type = object_type.substr(1, object_type.length()); if (!ClassDB::is_parent_class(object_type, p_native)) { ERR_EXPLAIN("Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'"); ERR_FAIL_V(NULL); } MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr()); ERR_FAIL_NULL_V(mono_object, NULL); CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object); // Construct mono_runtime_object_init(mono_object); return mono_object; }
MonoObject* ml_create_api_object(char *class_name) { MonoObject *obj = NULL; MonoClass *klass = NULL; klass = mono_class_from_name(ml_get_api_image(), "Purple", class_name); if (!klass) { purple_debug(PURPLE_DEBUG_FATAL, "mono", "couldn't find the '%s' class\n", class_name); return NULL; } obj = mono_object_new(ml_get_domain(), klass); if (!obj) { purple_debug(PURPLE_DEBUG_FATAL, "mono", "couldn't create the object from class '%s'\n", class_name); return NULL; } mono_runtime_object_init(obj); return obj; }
/** * mono_exception_from_name_domain: * @domain: Domain where the return object will be created. * @image: the Mono image where to look for the class * @name_space: the namespace for the class * @name: class name * * Creates an exception object of the given namespace/name class on * the given domain. * * Returns: the initialized exception instance. */ MonoException * mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, const char* name_space, const char *name) { MonoError error; MonoClass *klass; MonoObject *o; MonoDomain *caller_domain = mono_domain_get (); klass = mono_class_load_from_name (image, name_space, name); o = mono_object_new_checked (domain, klass, &error); g_assert (o != NULL && mono_error_ok (&error)); /* FIXME don't swallow the error */ if (domain != caller_domain) mono_domain_set_internal (domain); mono_runtime_object_init (o); if (domain != caller_domain) mono_domain_set_internal (caller_domain); return (MonoException *)o; }
void runtime_object_init(MonoObject *p_this_obj) { GD_MONO_BEGIN_RUNTIME_INVOKE; // FIXME: Do not use mono_runtime_object_init, it aborts if an exception is thrown mono_runtime_object_init(p_this_obj); GD_MONO_END_RUNTIME_INVOKE; }
bool Application::StartMonoAndLoadAssemblies() { // shutdown the child domain StopMono(); // create a new child domain if (!StartMono()) { mono_environment_exitcode_set(-1); return true; } std::string dll = "EmbedThings.dll"; std::string filename = File::BuildRootedPath(assemblyDir, dll); size_t length; // read our entry point assembly char* data = File::Read(filename.c_str(), &length); printf_console("Loading %s into Domain\n", dll.c_str()); MonoImageOpenStatus status; // open the assembly from the data we read, so we never lock files auto image = mono_image_open_from_data_with_name(data, length, true /* copy data */, &status, false /* ref only */, filename.c_str()); if (status != MONO_IMAGE_OK || image == nullptr) { printf_console("Failed loading assembly %s\n", dll); return true; } // load the assembly auto assembly = mono_assembly_load_from_full(image, filename.c_str(), &status, false); if (status != MONO_IMAGE_OK || assembly == nullptr) { mono_image_close(image); printf_console("Failed loading assembly %s\n", dll); return true; } // save the image for lookups later and for cleaning up images.push_back(image); if (!assembly) { printf_console("Couldn't find assembly %s\n", filename.c_str()); return true; } // locate the class we want to load MonoClass* klass = mono_class_from_name(image, "EmbedThings", "EntryPoint"); if (klass == nullptr) { printf_console("Failed loading class %s\n", "EmbedThings.EntryPoint"); return true; } // create the class (doesn't run constructors) MonoObject* obj = mono_object_new(mono_domain_get(), klass); if (obj == nullptr) { printf_console("Failed loading class instance %s\n", "EmbedThings.EntryPoint"); return true; } // initialize the class instance (runs default constructors) mono_runtime_object_init(obj); if (obj == nullptr) { printf_console("Failed initializing class instance %s\n", "EmbedThings.EntryPoint"); return true; } // save the class instance for lookups later instances.push_back(obj); // find the Run() method auto method = find_method(klass, "Run"); MonoObject *result, *exception; // call the Run method. This will block until the managed code decides to exit result = mono_runtime_invoke(method, obj, NULL, NULL); int val = *(int*)mono_object_unbox(result); // if the managed code returns with 0, it wants to exit completely if (val == 0) { return true; } return false; }
void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2)); CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2)); CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D)); CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3)); CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis)); CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat)); CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform)); CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB)); CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color)); CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane)); CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath)); CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(NodePath)); CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object)); CACHE_CLASS_AND_CHECK(GodotReference, GODOT_API_CLASS(Reference)); CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node)); CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control)); CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial)); CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef)); CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils)); #ifdef DEBUG_ENABLED CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils)); #endif // Attributes CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute)); CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint")); CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString")); CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute)); CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute)); CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute)); CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute)); CACHE_CLASS_AND_CHECK(SlaveAttribute, GODOT_API_CLASS(SlaveAttribute)); CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute)); CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName")); CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD)); CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD)); CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryToArrays, (MarshalUtils_DictToArrays)CACHED_CLASS(MarshalUtils)->get_method("DictionaryToArrays", 3)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArraysToDictionary, (MarshalUtils_ArraysToDict)CACHED_CLASS(MarshalUtils)->get_method("ArraysToDictionary", 2)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk()); #ifdef DEBUG_ENABLED CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk()); #endif { /* * TODO Right now we only support Dictionary<object, object>. * It would be great if we could support other key/value types * without forcing the user to copy the entries. */ GDMonoMethod *method_get_dict_type = CACHED_CLASS(MarshalUtils)->get_method("GetDictionaryType", 0); ERR_FAIL_NULL(method_get_dict_type); MonoReflectionType *dict_refl_type = (MonoReflectionType *)method_get_dict_type->invoke(NULL); ERR_FAIL_NULL(dict_refl_type); MonoType *dict_type = mono_reflection_type_get_type(dict_refl_type); ERR_FAIL_NULL(dict_type); CACHE_RAW_MONO_CLASS_AND_CHECK(Dictionary, mono_class_from_mono_type(dict_type)); } MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr()); mono_runtime_object_init(task_scheduler); mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); mono_cache.corlib_cache_updated = true; }
/* Create an instance of a type given its name, by calling its constructor with * no arguments. Note that result MUST be in the stack, or the garbage * collector may free it prematurely. */ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name, MonoDomain *domain, MonoObject **result) { HRESULT hr=S_OK; char *nameA=NULL; MonoType *type; MonoClass *klass; MonoObject *obj; if (!domain) hr = RuntimeHost_GetDefaultDomain(This, &domain); if (SUCCEEDED(hr)) { nameA = WtoA(name); if (!nameA) hr = E_OUTOFMEMORY; } if (SUCCEEDED(hr)) { mono_thread_attach(domain); type = mono_reflection_type_from_name(nameA, NULL); if (!type) { ERR("Cannot find type %s\n", debugstr_w(name)); hr = E_FAIL; } } if (SUCCEEDED(hr)) { klass = mono_class_from_mono_type(type); if (!klass) { ERR("Cannot convert type %s to a class\n", debugstr_w(name)); hr = E_FAIL; } } if (SUCCEEDED(hr)) { obj = mono_object_new(domain, klass); if (!obj) { ERR("Cannot allocate object of type %s\n", debugstr_w(name)); hr = E_FAIL; } } if (SUCCEEDED(hr)) { /* FIXME: Detect exceptions from the constructor? */ mono_runtime_object_init(obj); *result = obj; } HeapFree(GetProcessHeap(), 0, nameA); return hr; }
HRESULT create_monodata(REFIID riid, LPVOID *ppObj ) { static const WCHAR wszAssembly[] = {'A','s','s','e','m','b','l','y',0}; static const WCHAR wszCodebase[] = {'C','o','d','e','B','a','s','e',0}; static const WCHAR wszClass[] = {'C','l','a','s','s',0}; static const WCHAR wszFileSlash[] = {'f','i','l','e',':','/','/','/',0}; static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0}; static const WCHAR wszInprocServer32[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0}; static const WCHAR wszDLL[] = {'.','d','l','l',0}; WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1]; MonoDomain *domain; MonoAssembly *assembly; ICLRRuntimeInfo *info = NULL; RuntimeHost *host; HRESULT hr; HKEY key, subkey; LONG res; int offset = 0; DWORD numKeys, keyLength; WCHAR codebase[MAX_PATH + 8]; WCHAR classname[350], subkeyName[256]; WCHAR filename[MAX_PATH]; DWORD dwBufLen = 350; lstrcpyW(path, wszCLSIDSlash); StringFromGUID2(riid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID); lstrcatW(path, wszInprocServer32); TRACE("Registry key: %s\n", debugstr_w(path)); res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key); if (res == ERROR_FILE_NOT_FOUND) return CLASS_E_CLASSNOTAVAILABLE; res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen); if(res != ERROR_SUCCESS) { WARN("Class value cannot be found.\n"); hr = CLASS_E_CLASSNOTAVAILABLE; goto cleanup; } TRACE("classname (%s)\n", debugstr_w(classname)); dwBufLen = MAX_PATH + 8; res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen); if(res == ERROR_SUCCESS) { /* Strip file:/// */ if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0) offset = strlenW(wszFileSlash); strcpyW(filename, codebase + offset); } else { WCHAR assemblyname[MAX_PATH + 8]; hr = CLASS_E_CLASSNOTAVAILABLE; WARN("CodeBase value cannot be found, trying Assembly.\n"); /* get the last subkey of InprocServer32 */ res = RegQueryInfoKeyW(key, 0, 0, 0, &numKeys, 0, 0, 0, 0, 0, 0, 0); if (res != ERROR_SUCCESS || numKeys == 0) goto cleanup; numKeys--; keyLength = sizeof(subkeyName) / sizeof(WCHAR); res = RegEnumKeyExW(key, numKeys, subkeyName, &keyLength, 0, 0, 0, 0); if (res != ERROR_SUCCESS) goto cleanup; res = RegOpenKeyExW(key, subkeyName, 0, KEY_READ, &subkey); if (res != ERROR_SUCCESS) goto cleanup; dwBufLen = MAX_PATH + 8; res = RegGetValueW(subkey, NULL, wszAssembly, RRF_RT_REG_SZ, NULL, assemblyname, &dwBufLen); RegCloseKey(subkey); if (res != ERROR_SUCCESS) goto cleanup; hr = get_file_from_strongname(assemblyname, filename, MAX_PATH); if (!SUCCEEDED(hr)) { /* * The registry doesn't have a CodeBase entry and it's not in the GAC. * * Use the Assembly Key to retrieve the filename. * Assembly : REG_SZ : AssemblyName, Version=X.X.X.X, Culture=neutral, PublicKeyToken=null */ WCHAR *ns; WARN("Attempt to load from the application directory.\n"); GetModuleFileNameW(NULL, filename, MAX_PATH); ns = strrchrW(filename, '\\'); *(ns+1) = '\0'; ns = strchrW(assemblyname, ','); *(ns) = '\0'; strcatW(filename, assemblyname); *(ns) = '.'; strcatW(filename, wszDLL); } } TRACE("filename (%s)\n", debugstr_w(filename)); *ppObj = NULL; hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info); if (SUCCEEDED(hr)) { hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host); if (SUCCEEDED(hr)) hr = RuntimeHost_GetDefaultDomain(host, &domain); if (SUCCEEDED(hr)) { MonoImage *image; MonoClass *klass; MonoObject *result; IUnknown *unk = NULL; char *filenameA, *ns; char *classA; hr = CLASS_E_CLASSNOTAVAILABLE; mono_thread_attach(domain); filenameA = WtoA(filename); assembly = mono_domain_assembly_open(domain, filenameA); HeapFree(GetProcessHeap(), 0, filenameA); if (!assembly) { ERR("Cannot open assembly %s\n", filenameA); goto cleanup; } image = mono_assembly_get_image(assembly); if (!image) { ERR("Couldn't get assembly image\n"); goto cleanup; } classA = WtoA(classname); ns = strrchr(classA, '.'); *ns = '\0'; klass = mono_class_from_name(image, classA, ns+1); HeapFree(GetProcessHeap(), 0, classA); if (!klass) { ERR("Couldn't get class from image\n"); goto cleanup; } /* * Use the default constructor for the .NET class. */ result = mono_object_new(domain, klass); mono_runtime_object_init(result); hr = RuntimeHost_GetIUnknownForObject(host, result, &unk); if (SUCCEEDED(hr)) { hr = IUnknown_QueryInterface(unk, &IID_IUnknown, ppObj); IUnknown_Release(unk); } else hr = CLASS_E_CLASSNOTAVAILABLE; } else hr = CLASS_E_CLASSNOTAVAILABLE; } else hr = CLASS_E_CLASSNOTAVAILABLE; cleanup: if(info) ICLRRuntimeInfo_Release(info); RegCloseKey(key); return hr; }