gd_mono_utils.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /*************************************************************************/
  2. /* gd_mono_utils.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "gd_mono_utils.h"
  31. #include <mono/metadata/exception.h>
  32. #include "core/os/dir_access.h"
  33. #include "core/os/os.h"
  34. #include "core/project_settings.h"
  35. #include "core/reference.h"
  36. #ifdef TOOLS_ENABLED
  37. #include "editor/debugger/script_editor_debugger.h"
  38. #endif
  39. #include "../csharp_script.h"
  40. #include "../utils/macros.h"
  41. #include "../utils/mutex_utils.h"
  42. #include "gd_mono.h"
  43. #include "gd_mono_cache.h"
  44. #include "gd_mono_class.h"
  45. #include "gd_mono_marshal.h"
  46. #include "gd_mono_method_thunk.h"
  47. namespace GDMonoUtils {
  48. MonoObject *unmanaged_get_managed(Object *unmanaged) {
  49. if (!unmanaged)
  50. return NULL;
  51. if (unmanaged->get_script_instance()) {
  52. CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance());
  53. if (cs_instance) {
  54. return cs_instance->get_mono_object();
  55. }
  56. }
  57. // If the owner does not have a CSharpInstance...
  58. void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
  59. ERR_FAIL_NULL_V(data, NULL);
  60. CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value();
  61. if (!script_binding.inited) {
  62. SCOPED_MUTEX_LOCK(CSharpLanguage::get_singleton()->get_language_bind_mutex());
  63. if (!script_binding.inited) { // Other thread may have set it up
  64. // Already had a binding that needs to be setup
  65. CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged);
  66. ERR_FAIL_COND_V(!script_binding.inited, NULL);
  67. }
  68. }
  69. Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
  70. ERR_FAIL_COND_V(gchandle.is_null(), NULL);
  71. MonoObject *target = gchandle->get_target();
  72. if (target)
  73. return target;
  74. CSharpLanguage::get_singleton()->release_script_gchandle(gchandle);
  75. // Create a new one
  76. #ifdef DEBUG_ENABLED
  77. CRASH_COND(script_binding.type_name == StringName());
  78. CRASH_COND(script_binding.wrapper_class == NULL);
  79. #endif
  80. MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(script_binding.wrapper_class, script_binding.type_name, unmanaged);
  81. ERR_FAIL_NULL_V(mono_object, NULL);
  82. gchandle->set_handle(MonoGCHandle::new_strong_handle(mono_object), MonoGCHandle::STRONG_HANDLE);
  83. // Tie managed to unmanaged
  84. Reference *ref = Object::cast_to<Reference>(unmanaged);
  85. if (ref) {
  86. // Unsafe refcount increment. The managed instance also counts as a reference.
  87. // This way if the unmanaged world has no references to our owner
  88. // but the managed instance is alive, the refcount will be 1 instead of 0.
  89. // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
  90. ref->reference();
  91. CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
  92. }
  93. return mono_object;
  94. }
  95. void set_main_thread(MonoThread *p_thread) {
  96. mono_thread_set_main(p_thread);
  97. }
  98. MonoThread *attach_current_thread() {
  99. ERR_FAIL_COND_V(!GDMono::get_singleton()->is_runtime_initialized(), NULL);
  100. MonoDomain *scripts_domain = GDMono::get_singleton()->get_scripts_domain();
  101. MonoThread *mono_thread = mono_thread_attach(scripts_domain ? scripts_domain : mono_get_root_domain());
  102. ERR_FAIL_NULL_V(mono_thread, NULL);
  103. return mono_thread;
  104. }
  105. void detach_current_thread() {
  106. ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
  107. MonoThread *mono_thread = mono_thread_current();
  108. ERR_FAIL_NULL(mono_thread);
  109. mono_thread_detach(mono_thread);
  110. }
  111. void detach_current_thread(MonoThread *p_mono_thread) {
  112. ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
  113. ERR_FAIL_NULL(p_mono_thread);
  114. mono_thread_detach(p_mono_thread);
  115. }
  116. MonoThread *get_current_thread() {
  117. return mono_thread_current();
  118. }
  119. bool is_thread_attached() {
  120. return mono_domain_get() != NULL;
  121. }
  122. void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) {
  123. GDMonoMethod *ctor = p_class->get_method(".ctor", 0);
  124. ERR_FAIL_NULL(ctor);
  125. ctor->invoke_raw(p_this_obj, NULL, r_exc);
  126. }
  127. GDMonoClass *get_object_class(MonoObject *p_object) {
  128. return GDMono::get_singleton()->get_class(mono_object_get_class(p_object));
  129. }
  130. GDMonoClass *type_get_proxy_class(const StringName &p_type) {
  131. String class_name = p_type;
  132. if (class_name[0] == '_')
  133. class_name = class_name.substr(1, class_name.length());
  134. GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
  135. if (klass && klass->is_static()) {
  136. // A static class means this is a Godot singleton class. If an instance is needed we use Godot.Object.
  137. return GDMonoCache::cached_data.class_GodotObject;
  138. }
  139. #ifdef TOOLS_ENABLED
  140. if (!klass) {
  141. return GDMono::get_singleton()->get_editor_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
  142. }
  143. #endif
  144. return klass;
  145. }
  146. GDMonoClass *get_class_native_base(GDMonoClass *p_class) {
  147. GDMonoClass *klass = p_class;
  148. do {
  149. const GDMonoAssembly *assembly = klass->get_assembly();
  150. if (assembly == GDMono::get_singleton()->get_core_api_assembly())
  151. return klass;
  152. #ifdef TOOLS_ENABLED
  153. if (assembly == GDMono::get_singleton()->get_editor_api_assembly())
  154. return klass;
  155. #endif
  156. } while ((klass = klass->get_parent_class()) != NULL);
  157. return NULL;
  158. }
  159. MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) {
  160. bool parent_is_object_class = ClassDB::is_parent_class(p_object->get_class_name(), p_native);
  161. ERR_FAIL_COND_V_MSG(!parent_is_object_class, NULL,
  162. "Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'.");
  163. MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
  164. ERR_FAIL_NULL_V(mono_object, NULL);
  165. CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
  166. // Construct
  167. GDMonoUtils::runtime_object_init(mono_object, p_class);
  168. return mono_object;
  169. }
  170. MonoObject *create_managed_from(const NodePath &p_from) {
  171. MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(NodePath));
  172. ERR_FAIL_NULL_V(mono_object, NULL);
  173. // Construct
  174. GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(NodePath));
  175. CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
  176. return mono_object;
  177. }
  178. MonoObject *create_managed_from(const RID &p_from) {
  179. MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(RID));
  180. ERR_FAIL_NULL_V(mono_object, NULL);
  181. // Construct
  182. GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(RID));
  183. CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
  184. return mono_object;
  185. }
  186. MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) {
  187. MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
  188. ERR_FAIL_NULL_V(mono_object, NULL);
  189. // Search constructor that takes a pointer as parameter
  190. MonoMethod *m;
  191. void *iter = NULL;
  192. while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
  193. if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
  194. MonoMethodSignature *sig = mono_method_signature(m);
  195. void *front = NULL;
  196. if (mono_signature_get_param_count(sig) == 1 &&
  197. mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
  198. break;
  199. }
  200. }
  201. }
  202. CRASH_COND(m == NULL);
  203. Array *new_array = memnew(Array(p_from));
  204. void *args[1] = { &new_array };
  205. MonoException *exc = NULL;
  206. GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
  207. UNHANDLED_EXCEPTION(exc);
  208. return mono_object;
  209. }
  210. MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) {
  211. MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
  212. ERR_FAIL_NULL_V(mono_object, NULL);
  213. // Search constructor that takes a pointer as parameter
  214. MonoMethod *m;
  215. void *iter = NULL;
  216. while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
  217. if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
  218. MonoMethodSignature *sig = mono_method_signature(m);
  219. void *front = NULL;
  220. if (mono_signature_get_param_count(sig) == 1 &&
  221. mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
  222. break;
  223. }
  224. }
  225. }
  226. CRASH_COND(m == NULL);
  227. Dictionary *new_dict = memnew(Dictionary(p_from));
  228. void *args[1] = { &new_dict };
  229. MonoException *exc = NULL;
  230. GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
  231. UNHANDLED_EXCEPTION(exc);
  232. return mono_object;
  233. }
  234. MonoDomain *create_domain(const String &p_friendly_name) {
  235. print_verbose("Mono: Creating domain '" + p_friendly_name + "'...");
  236. MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL);
  237. if (domain) {
  238. // Workaround to avoid this exception:
  239. // System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system.
  240. // ---> System.ArgumentException: The 'ExeConfigFilename' argument cannot be null.
  241. mono_domain_set_config(domain, ".", "");
  242. }
  243. return domain;
  244. }
  245. String get_exception_name_and_message(MonoException *p_exc) {
  246. String res;
  247. MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
  248. MonoType *type = mono_class_get_type(klass);
  249. char *full_name = mono_type_full_name(type);
  250. res += full_name;
  251. mono_free(full_name);
  252. res += ": ";
  253. MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
  254. MonoString *msg = (MonoString *)property_get_value(prop, (MonoObject *)p_exc, NULL, NULL);
  255. res += GDMonoMarshal::mono_string_to_godot(msg);
  256. return res;
  257. }
  258. void set_exception_message(MonoException *p_exc, String message) {
  259. MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
  260. MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
  261. MonoString *msg = GDMonoMarshal::mono_string_from_godot(message);
  262. void *params[1] = { msg };
  263. property_set_value(prop, (MonoObject *)p_exc, params, NULL);
  264. }
  265. void debug_print_unhandled_exception(MonoException *p_exc) {
  266. print_unhandled_exception(p_exc);
  267. debug_send_unhandled_exception_error(p_exc);
  268. }
  269. void debug_send_unhandled_exception_error(MonoException *p_exc) {
  270. #ifdef DEBUG_ENABLED
  271. if (!ScriptDebugger::get_singleton()) {
  272. #ifdef TOOLS_ENABLED
  273. if (Engine::get_singleton()->is_editor_hint()) {
  274. ERR_PRINT(GDMonoUtils::get_exception_name_and_message(p_exc));
  275. }
  276. #endif
  277. return;
  278. }
  279. _TLS_RECURSION_GUARD_;
  280. ScriptLanguage::StackInfo separator;
  281. separator.file = String();
  282. separator.func = "--- " + RTR("End of inner exception stack trace") + " ---";
  283. separator.line = 0;
  284. Vector<ScriptLanguage::StackInfo> si;
  285. String exc_msg;
  286. while (p_exc != NULL) {
  287. GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace);
  288. MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr());
  289. MonoBoolean need_file_info = true;
  290. void *ctor_args[2] = { p_exc, &need_file_info };
  291. MonoException *unexpected_exc = NULL;
  292. CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc);
  293. if (unexpected_exc) {
  294. GDMonoInternals::unhandled_exception(unexpected_exc);
  295. return;
  296. }
  297. Vector<ScriptLanguage::StackInfo> _si;
  298. if (stack_trace != NULL) {
  299. _si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace);
  300. for (int i = _si.size() - 1; i >= 0; i--)
  301. si.insert(0, _si[i]);
  302. }
  303. exc_msg += (exc_msg.length() > 0 ? " ---> " : "") + GDMonoUtils::get_exception_name_and_message(p_exc);
  304. GDMonoClass *exc_class = GDMono::get_singleton()->get_class(mono_get_exception_class());
  305. GDMonoProperty *inner_exc_prop = exc_class->get_property("InnerException");
  306. CRASH_COND(inner_exc_prop == NULL);
  307. MonoObject *inner_exc = inner_exc_prop->get_value((MonoObject *)p_exc);
  308. if (inner_exc != NULL)
  309. si.insert(0, separator);
  310. p_exc = (MonoException *)inner_exc;
  311. }
  312. String file = si.size() ? si[0].file : __FILE__;
  313. String func = si.size() ? si[0].func : FUNCTION_STR;
  314. int line = si.size() ? si[0].line : __LINE__;
  315. String error_msg = "Unhandled exception";
  316. ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si);
  317. #endif
  318. }
  319. void debug_unhandled_exception(MonoException *p_exc) {
  320. GDMonoInternals::unhandled_exception(p_exc); // prints the exception as well
  321. }
  322. void print_unhandled_exception(MonoException *p_exc) {
  323. mono_print_unhandled_exception((MonoObject *)p_exc);
  324. }
  325. void set_pending_exception(MonoException *p_exc) {
  326. #ifdef NO_PENDING_EXCEPTIONS
  327. debug_unhandled_exception(p_exc);
  328. #else
  329. if (get_runtime_invoke_count() == 0) {
  330. debug_unhandled_exception(p_exc);
  331. }
  332. if (!mono_runtime_set_pending_exception(p_exc, false)) {
  333. ERR_PRINT("Exception thrown from managed code, but it could not be set as pending:");
  334. GDMonoUtils::debug_print_unhandled_exception(p_exc);
  335. }
  336. #endif
  337. }
  338. _THREAD_LOCAL_(int)
  339. current_invoke_count = 0;
  340. MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc) {
  341. GD_MONO_BEGIN_RUNTIME_INVOKE;
  342. MonoObject *ret = mono_runtime_invoke(p_method, p_obj, p_params, (MonoObject **)r_exc);
  343. GD_MONO_END_RUNTIME_INVOKE;
  344. return ret;
  345. }
  346. MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc) {
  347. GD_MONO_BEGIN_RUNTIME_INVOKE;
  348. MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)r_exc);
  349. GD_MONO_END_RUNTIME_INVOKE;
  350. return ret;
  351. }
  352. MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc) {
  353. GD_MONO_BEGIN_RUNTIME_INVOKE;
  354. MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)r_exc);
  355. GD_MONO_END_RUNTIME_INVOKE;
  356. return ret;
  357. }
  358. void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
  359. GD_MONO_BEGIN_RUNTIME_INVOKE;
  360. mono_property_set_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
  361. GD_MONO_END_RUNTIME_INVOKE;
  362. }
  363. MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
  364. GD_MONO_BEGIN_RUNTIME_INVOKE;
  365. MonoObject *ret = mono_property_get_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
  366. GD_MONO_END_RUNTIME_INVOKE;
  367. return ret;
  368. }
  369. uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error) {
  370. r_error = false;
  371. switch (mono_type_get_type(p_enum_basetype)) {
  372. case MONO_TYPE_BOOLEAN:
  373. return (bool)GDMonoMarshal::unbox<MonoBoolean>(p_boxed) ? 1 : 0;
  374. case MONO_TYPE_CHAR:
  375. return GDMonoMarshal::unbox<uint16_t>(p_boxed);
  376. case MONO_TYPE_U1:
  377. return GDMonoMarshal::unbox<uint8_t>(p_boxed);
  378. case MONO_TYPE_U2:
  379. return GDMonoMarshal::unbox<uint16_t>(p_boxed);
  380. case MONO_TYPE_U4:
  381. return GDMonoMarshal::unbox<uint32_t>(p_boxed);
  382. case MONO_TYPE_U8:
  383. return GDMonoMarshal::unbox<uint64_t>(p_boxed);
  384. case MONO_TYPE_I1:
  385. return GDMonoMarshal::unbox<int8_t>(p_boxed);
  386. case MONO_TYPE_I2:
  387. return GDMonoMarshal::unbox<int16_t>(p_boxed);
  388. case MONO_TYPE_I4:
  389. return GDMonoMarshal::unbox<int32_t>(p_boxed);
  390. case MONO_TYPE_I8:
  391. return GDMonoMarshal::unbox<int64_t>(p_boxed);
  392. default:
  393. r_error = true;
  394. return 0;
  395. }
  396. }
  397. void dispose(MonoObject *p_mono_object, MonoException **r_exc) {
  398. CACHED_METHOD_THUNK(GodotObject, Dispose).invoke(p_mono_object, r_exc);
  399. }
  400. namespace Marshal {
  401. #ifdef MONO_GLUE_ENABLED
  402. #ifdef TOOLS_ENABLED
  403. #define NO_GLUE_RET(m_ret) \
  404. { \
  405. if (!GDMonoCache::cached_data.godot_api_cache_updated) return m_ret; \
  406. }
  407. #else
  408. #define NO_GLUE_RET(m_ret) \
  409. {}
  410. #endif
  411. #else
  412. #define NO_GLUE_RET(m_ret) \
  413. { return m_ret; }
  414. #endif
  415. bool type_is_generic_array(MonoReflectionType *p_reftype) {
  416. NO_GLUE_RET(false);
  417. MonoException *exc = NULL;
  418. MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray).invoke(p_reftype, &exc);
  419. UNHANDLED_EXCEPTION(exc);
  420. return (bool)res;
  421. }
  422. bool type_is_generic_dictionary(MonoReflectionType *p_reftype) {
  423. NO_GLUE_RET(false);
  424. MonoException *exc = NULL;
  425. MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary).invoke(p_reftype, &exc);
  426. UNHANDLED_EXCEPTION(exc);
  427. return (bool)res;
  428. }
  429. void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) {
  430. MonoException *exc = NULL;
  431. CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType).invoke(p_array_reftype, r_elem_reftype, &exc);
  432. UNHANDLED_EXCEPTION(exc);
  433. }
  434. void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
  435. MonoException *exc = NULL;
  436. CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes).invoke(p_dict_reftype, r_key_reftype, r_value_reftype, &exc);
  437. UNHANDLED_EXCEPTION(exc);
  438. }
  439. bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) {
  440. NO_GLUE_RET(false);
  441. MonoException *exc = NULL;
  442. MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType).invoke(p_reftype, &exc);
  443. UNHANDLED_EXCEPTION(exc);
  444. return (bool)res;
  445. }
  446. bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) {
  447. NO_GLUE_RET(false);
  448. MonoException *exc = NULL;
  449. MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType).invoke(p_reftype, &exc);
  450. UNHANDLED_EXCEPTION(exc);
  451. return (bool)res;
  452. }
  453. bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) {
  454. NO_GLUE_RET(false);
  455. MonoException *exc = NULL;
  456. MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info).invoke(p_reftype, r_elem_reftype, &exc);
  457. UNHANDLED_EXCEPTION(exc);
  458. return (bool)res;
  459. }
  460. bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
  461. NO_GLUE_RET(false);
  462. MonoException *exc = NULL;
  463. MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info).invoke(p_reftype, r_key_reftype, r_value_reftype, &exc);
  464. UNHANDLED_EXCEPTION(exc);
  465. return (bool)res;
  466. }
  467. Array enumerable_to_array(MonoObject *p_enumerable) {
  468. NO_GLUE_RET(Array());
  469. Array result;
  470. MonoException *exc = NULL;
  471. CACHED_METHOD_THUNK(MarshalUtils, EnumerableToArray).invoke(p_enumerable, &result, &exc);
  472. UNHANDLED_EXCEPTION(exc);
  473. return result;
  474. }
  475. Dictionary idictionary_to_dictionary(MonoObject *p_idictionary) {
  476. NO_GLUE_RET(Dictionary());
  477. Dictionary result;
  478. MonoException *exc = NULL;
  479. CACHED_METHOD_THUNK(MarshalUtils, IDictionaryToDictionary).invoke(p_idictionary, &result, &exc);
  480. UNHANDLED_EXCEPTION(exc);
  481. return result;
  482. }
  483. Dictionary generic_idictionary_to_dictionary(MonoObject *p_generic_idictionary) {
  484. NO_GLUE_RET(Dictionary());
  485. Dictionary result;
  486. MonoException *exc = NULL;
  487. CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryToDictionary).invoke(p_generic_idictionary, &result, &exc);
  488. UNHANDLED_EXCEPTION(exc);
  489. return result;
  490. }
  491. GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype) {
  492. NO_GLUE_RET(NULL);
  493. MonoException *exc = NULL;
  494. MonoReflectionType *reftype = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericArrayType).invoke(p_elem_reftype, &exc);
  495. UNHANDLED_EXCEPTION(exc);
  496. return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
  497. }
  498. GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) {
  499. NO_GLUE_RET(NULL);
  500. MonoException *exc = NULL;
  501. MonoReflectionType *reftype = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericDictionaryType).invoke(p_key_reftype, p_value_reftype, &exc);
  502. UNHANDLED_EXCEPTION(exc);
  503. return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
  504. }
  505. } // namespace Marshal
  506. ScopeThreadAttach::ScopeThreadAttach() :
  507. mono_thread(NULL) {
  508. if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) {
  509. mono_thread = GDMonoUtils::attach_current_thread();
  510. }
  511. }
  512. ScopeThreadAttach::~ScopeThreadAttach() {
  513. if (unlikely(mono_thread)) {
  514. GDMonoUtils::detach_current_thread(mono_thread);
  515. }
  516. }
  517. // namespace Marshal
  518. } // namespace GDMonoUtils