gd_mono_utils.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  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-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 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/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_class.h"
  44. #include "gd_mono_marshal.h"
  45. namespace GDMonoUtils {
  46. MonoCache mono_cache;
  47. #define CACHE_AND_CHECK(m_var, m_val) \
  48. { \
  49. CRASH_COND(m_var != NULL); \
  50. m_var = m_val; \
  51. ERR_FAIL_COND_MSG(!m_var, "Mono Cache: Member " #m_var " is null."); \
  52. }
  53. #define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_class, m_val)
  54. #define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_ns##_##m_class, m_val)
  55. #define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val)
  56. #define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
  57. #define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val)
  58. #define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
  59. #define CACHE_PROPERTY_AND_CHECK(m_class, m_property, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.property_##m_class##_##m_property, m_val)
  60. void MonoCache::clear_corlib_cache() {
  61. corlib_cache_updated = false;
  62. class_MonoObject = NULL;
  63. class_bool = NULL;
  64. class_int8_t = NULL;
  65. class_int16_t = NULL;
  66. class_int32_t = NULL;
  67. class_int64_t = NULL;
  68. class_uint8_t = NULL;
  69. class_uint16_t = NULL;
  70. class_uint32_t = NULL;
  71. class_uint64_t = NULL;
  72. class_float = NULL;
  73. class_double = NULL;
  74. class_String = NULL;
  75. class_IntPtr = NULL;
  76. class_System_Collections_IEnumerable = NULL;
  77. class_System_Collections_IDictionary = NULL;
  78. #ifdef DEBUG_ENABLED
  79. class_System_Diagnostics_StackTrace = NULL;
  80. methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL;
  81. method_System_Diagnostics_StackTrace_ctor_bool = NULL;
  82. method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL;
  83. #endif
  84. class_KeyNotFoundException = NULL;
  85. }
  86. void MonoCache::clear_godot_api_cache() {
  87. godot_api_cache_updated = false;
  88. rawclass_Dictionary = NULL;
  89. class_Vector2 = NULL;
  90. class_Rect2 = NULL;
  91. class_Transform2D = NULL;
  92. class_Vector3 = NULL;
  93. class_Basis = NULL;
  94. class_Quat = NULL;
  95. class_Transform = NULL;
  96. class_AABB = NULL;
  97. class_Color = NULL;
  98. class_Plane = NULL;
  99. class_NodePath = NULL;
  100. class_RID = NULL;
  101. class_GodotObject = NULL;
  102. class_GodotResource = NULL;
  103. class_Node = NULL;
  104. class_Control = NULL;
  105. class_Spatial = NULL;
  106. class_WeakRef = NULL;
  107. class_Array = NULL;
  108. class_Dictionary = NULL;
  109. class_MarshalUtils = NULL;
  110. class_ISerializationListener = NULL;
  111. #ifdef DEBUG_ENABLED
  112. class_DebuggingUtils = NULL;
  113. methodthunk_DebuggingUtils_GetStackFrameInfo = NULL;
  114. #endif
  115. class_ExportAttribute = NULL;
  116. field_ExportAttribute_hint = NULL;
  117. field_ExportAttribute_hintString = NULL;
  118. class_SignalAttribute = NULL;
  119. class_ToolAttribute = NULL;
  120. class_RemoteAttribute = NULL;
  121. class_SyncAttribute = NULL;
  122. class_MasterAttribute = NULL;
  123. class_PuppetAttribute = NULL;
  124. class_SlaveAttribute = NULL;
  125. class_RemoteSyncAttribute = NULL;
  126. class_MasterSyncAttribute = NULL;
  127. class_PuppetSyncAttribute = NULL;
  128. class_GodotMethodAttribute = NULL;
  129. field_GodotMethodAttribute_methodName = NULL;
  130. field_GodotObject_ptr = NULL;
  131. field_NodePath_ptr = NULL;
  132. field_Image_ptr = NULL;
  133. field_RID_ptr = NULL;
  134. methodthunk_GodotObject_Dispose = NULL;
  135. methodthunk_Array_GetPtr = NULL;
  136. methodthunk_Dictionary_GetPtr = NULL;
  137. methodthunk_SignalAwaiter_SignalCallback = NULL;
  138. methodthunk_SignalAwaiter_FailureCallback = NULL;
  139. methodthunk_GodotTaskScheduler_Activate = NULL;
  140. // Start of MarshalUtils methods
  141. methodthunk_MarshalUtils_TypeIsGenericArray = NULL;
  142. methodthunk_MarshalUtils_TypeIsGenericDictionary = NULL;
  143. methodthunk_MarshalUtils_ArrayGetElementType = NULL;
  144. methodthunk_MarshalUtils_DictionaryGetKeyValueTypes = NULL;
  145. methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType = NULL;
  146. methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType = NULL;
  147. methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info = NULL;
  148. methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info = NULL;
  149. methodthunk_MarshalUtils_MakeGenericArrayType = NULL;
  150. methodthunk_MarshalUtils_MakeGenericDictionaryType = NULL;
  151. methodthunk_MarshalUtils_EnumerableToArray = NULL;
  152. methodthunk_MarshalUtils_IDictionaryToDictionary = NULL;
  153. methodthunk_MarshalUtils_GenericIDictionaryToDictionary = NULL;
  154. // End of MarshalUtils methods
  155. task_scheduler_handle = Ref<MonoGCHandle>();
  156. }
  157. #define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
  158. #define GODOT_API_NS_CLAS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class))
  159. void update_corlib_cache() {
  160. CACHE_CLASS_AND_CHECK(MonoObject, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_object_class()));
  161. CACHE_CLASS_AND_CHECK(bool, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_boolean_class()));
  162. CACHE_CLASS_AND_CHECK(int8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_sbyte_class()));
  163. CACHE_CLASS_AND_CHECK(int16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int16_class()));
  164. CACHE_CLASS_AND_CHECK(int32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int32_class()));
  165. CACHE_CLASS_AND_CHECK(int64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int64_class()));
  166. CACHE_CLASS_AND_CHECK(uint8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_byte_class()));
  167. CACHE_CLASS_AND_CHECK(uint16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint16_class()));
  168. CACHE_CLASS_AND_CHECK(uint32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint32_class()));
  169. CACHE_CLASS_AND_CHECK(uint64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint64_class()));
  170. CACHE_CLASS_AND_CHECK(float, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_single_class()));
  171. CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class()));
  172. CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
  173. CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
  174. CACHE_CLASS_AND_CHECK(System_Collections_IEnumerable, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IEnumerable"));
  175. CACHE_CLASS_AND_CHECK(System_Collections_IDictionary, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IDictionary"));
  176. #ifdef DEBUG_ENABLED
  177. CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace"));
  178. CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_thunk("GetFrames"));
  179. CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true));
  180. CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true));
  181. #endif
  182. CACHE_CLASS_AND_CHECK(KeyNotFoundException, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections.Generic", "KeyNotFoundException"));
  183. mono_cache.corlib_cache_updated = true;
  184. }
  185. void update_godot_api_cache() {
  186. CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2));
  187. CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2));
  188. CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D));
  189. CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3));
  190. CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
  191. CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat));
  192. CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform));
  193. CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB));
  194. CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
  195. CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
  196. CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath));
  197. CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(RID));
  198. CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object));
  199. CACHE_CLASS_AND_CHECK(GodotResource, GODOT_API_CLASS(Resource));
  200. CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
  201. CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
  202. CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
  203. CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
  204. CACHE_CLASS_AND_CHECK(Array, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array));
  205. CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary));
  206. CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
  207. CACHE_CLASS_AND_CHECK(ISerializationListener, GODOT_API_CLASS(ISerializationListener));
  208. #ifdef DEBUG_ENABLED
  209. CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils));
  210. #endif
  211. // Attributes
  212. CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
  213. CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
  214. CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString"));
  215. CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute));
  216. CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
  217. CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute));
  218. CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute));
  219. CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute));
  220. CACHE_CLASS_AND_CHECK(PuppetAttribute, GODOT_API_CLASS(PuppetAttribute));
  221. CACHE_CLASS_AND_CHECK(SlaveAttribute, GODOT_API_CLASS(SlaveAttribute));
  222. CACHE_CLASS_AND_CHECK(RemoteSyncAttribute, GODOT_API_CLASS(RemoteSyncAttribute));
  223. CACHE_CLASS_AND_CHECK(MasterSyncAttribute, GODOT_API_CLASS(MasterSyncAttribute));
  224. CACHE_CLASS_AND_CHECK(PuppetSyncAttribute, GODOT_API_CLASS(PuppetSyncAttribute));
  225. CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
  226. CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
  227. CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD));
  228. CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD));
  229. CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD));
  230. CACHE_METHOD_THUNK_AND_CHECK(GodotObject, Dispose, (GodotObject_Dispose)CACHED_CLASS(GodotObject)->get_method_thunk("Dispose", 0));
  231. CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array)->get_method_thunk("GetPtr", 0));
  232. CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)->get_method_thunk("GetPtr", 0));
  233. CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("SignalCallback", 1));
  234. CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("FailureCallback", 0));
  235. CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method_thunk("Activate", 0));
  236. // Start of MarshalUtils methods
  237. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, (TypeIsGenericArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericArray", 1));
  238. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericDictionary, (TypeIsGenericDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericDictionary", 1));
  239. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
  240. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
  241. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, (GenericIEnumerableIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 1));
  242. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, (GenericIDictionaryIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 1));
  243. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 2));
  244. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info, (GenericIDictionaryIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3));
  245. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, (MakeGenericArrayType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericArrayType", 1));
  246. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, (MakeGenericDictionaryType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericDictionaryType", 2));
  247. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, EnumerableToArray, (EnumerableToArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("EnumerableToArray", 2));
  248. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IDictionaryToDictionary, (IDictionaryToDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IDictionaryToDictionary", 2));
  249. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryToDictionary, (GenericIDictionaryToDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryToDictionary", 2));
  250. // End of MarshalUtils methods
  251. #ifdef DEBUG_ENABLED
  252. CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method_thunk("GetStackFrameInfo", 4));
  253. #endif
  254. // TODO Move to CSharpLanguage::init() and do handle disposal
  255. MonoObject *task_scheduler = mono_object_new(mono_domain_get(), GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
  256. GDMonoUtils::runtime_object_init(task_scheduler, GODOT_API_CLASS(GodotTaskScheduler));
  257. mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
  258. mono_cache.godot_api_cache_updated = true;
  259. }
  260. MonoObject *unmanaged_get_managed(Object *unmanaged) {
  261. if (!unmanaged)
  262. return NULL;
  263. if (unmanaged->get_script_instance()) {
  264. CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance());
  265. if (cs_instance) {
  266. return cs_instance->get_mono_object();
  267. }
  268. }
  269. // If the owner does not have a CSharpInstance...
  270. void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
  271. ERR_FAIL_NULL_V(data, NULL);
  272. CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value();
  273. if (!script_binding.inited) {
  274. SCOPED_MUTEX_LOCK(CSharpLanguage::get_singleton()->get_language_bind_mutex());
  275. if (!script_binding.inited) { // Other thread may have set it up
  276. // Already had a binding that needs to be setup
  277. CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged);
  278. ERR_FAIL_COND_V(!script_binding.inited, NULL);
  279. }
  280. }
  281. Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
  282. ERR_FAIL_COND_V(gchandle.is_null(), NULL);
  283. MonoObject *target = gchandle->get_target();
  284. if (target)
  285. return target;
  286. CSharpLanguage::get_singleton()->release_script_gchandle(gchandle);
  287. // Create a new one
  288. #ifdef DEBUG_ENABLED
  289. CRASH_COND(script_binding.type_name == StringName());
  290. CRASH_COND(script_binding.wrapper_class == NULL);
  291. #endif
  292. MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(script_binding.wrapper_class, script_binding.type_name, unmanaged);
  293. ERR_FAIL_NULL_V(mono_object, NULL);
  294. gchandle->set_handle(MonoGCHandle::new_strong_handle(mono_object), MonoGCHandle::STRONG_HANDLE);
  295. // Tie managed to unmanaged
  296. Reference *ref = Object::cast_to<Reference>(unmanaged);
  297. if (ref) {
  298. // Unsafe refcount increment. The managed instance also counts as a reference.
  299. // This way if the unmanaged world has no references to our owner
  300. // but the managed instance is alive, the refcount will be 1 instead of 0.
  301. // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
  302. ref->reference();
  303. }
  304. return mono_object;
  305. }
  306. void set_main_thread(MonoThread *p_thread) {
  307. mono_thread_set_main(p_thread);
  308. }
  309. void attach_current_thread() {
  310. ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
  311. MonoThread *mono_thread = mono_thread_attach(mono_domain_get());
  312. ERR_FAIL_NULL(mono_thread);
  313. }
  314. void detach_current_thread() {
  315. ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
  316. MonoThread *mono_thread = mono_thread_current();
  317. ERR_FAIL_NULL(mono_thread);
  318. mono_thread_detach(mono_thread);
  319. }
  320. MonoThread *get_current_thread() {
  321. return mono_thread_current();
  322. }
  323. void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) {
  324. GDMonoMethod *ctor = p_class->get_method(".ctor", 0);
  325. ERR_FAIL_NULL(ctor);
  326. ctor->invoke_raw(p_this_obj, NULL, r_exc);
  327. }
  328. GDMonoClass *get_object_class(MonoObject *p_object) {
  329. return GDMono::get_singleton()->get_class(mono_object_get_class(p_object));
  330. }
  331. GDMonoClass *type_get_proxy_class(const StringName &p_type) {
  332. String class_name = p_type;
  333. if (class_name[0] == '_')
  334. class_name = class_name.substr(1, class_name.length());
  335. GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
  336. if (klass && klass->is_static()) {
  337. // A static class means this is a Godot singleton class. If an instance is needed we use Godot.Object.
  338. return mono_cache.class_GodotObject;
  339. }
  340. #ifdef TOOLS_ENABLED
  341. if (!klass) {
  342. return GDMono::get_singleton()->get_editor_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
  343. }
  344. #endif
  345. return klass;
  346. }
  347. GDMonoClass *get_class_native_base(GDMonoClass *p_class) {
  348. GDMonoClass *klass = p_class;
  349. do {
  350. const GDMonoAssembly *assembly = klass->get_assembly();
  351. if (assembly == GDMono::get_singleton()->get_core_api_assembly())
  352. return klass;
  353. #ifdef TOOLS_ENABLED
  354. if (assembly == GDMono::get_singleton()->get_editor_api_assembly())
  355. return klass;
  356. #endif
  357. } while ((klass = klass->get_parent_class()) != NULL);
  358. return NULL;
  359. }
  360. MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) {
  361. bool parent_is_object_class = ClassDB::is_parent_class(p_object->get_class_name(), p_native);
  362. ERR_FAIL_COND_V_MSG(!parent_is_object_class, NULL,
  363. "Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'.");
  364. MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
  365. ERR_FAIL_NULL_V(mono_object, NULL);
  366. CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
  367. // Construct
  368. GDMonoUtils::runtime_object_init(mono_object, p_class);
  369. return mono_object;
  370. }
  371. MonoObject *create_managed_from(const NodePath &p_from) {
  372. MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(NodePath));
  373. ERR_FAIL_NULL_V(mono_object, NULL);
  374. // Construct
  375. GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(NodePath));
  376. CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
  377. return mono_object;
  378. }
  379. MonoObject *create_managed_from(const RID &p_from) {
  380. MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(RID));
  381. ERR_FAIL_NULL_V(mono_object, NULL);
  382. // Construct
  383. GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(RID));
  384. CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
  385. return mono_object;
  386. }
  387. MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) {
  388. MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
  389. ERR_FAIL_NULL_V(mono_object, NULL);
  390. // Search constructor that takes a pointer as parameter
  391. MonoMethod *m;
  392. void *iter = NULL;
  393. while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
  394. if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
  395. MonoMethodSignature *sig = mono_method_signature(m);
  396. void *front = NULL;
  397. if (mono_signature_get_param_count(sig) == 1 &&
  398. mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
  399. break;
  400. }
  401. }
  402. }
  403. CRASH_COND(m == NULL);
  404. Array *new_array = memnew(Array(p_from));
  405. void *args[1] = { &new_array };
  406. MonoException *exc = NULL;
  407. GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
  408. UNHANDLED_EXCEPTION(exc);
  409. return mono_object;
  410. }
  411. MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) {
  412. MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
  413. ERR_FAIL_NULL_V(mono_object, NULL);
  414. // Search constructor that takes a pointer as parameter
  415. MonoMethod *m;
  416. void *iter = NULL;
  417. while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
  418. if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
  419. MonoMethodSignature *sig = mono_method_signature(m);
  420. void *front = NULL;
  421. if (mono_signature_get_param_count(sig) == 1 &&
  422. mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
  423. break;
  424. }
  425. }
  426. }
  427. CRASH_COND(m == NULL);
  428. Dictionary *new_dict = memnew(Dictionary(p_from));
  429. void *args[1] = { &new_dict };
  430. MonoException *exc = NULL;
  431. GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
  432. UNHANDLED_EXCEPTION(exc);
  433. return mono_object;
  434. }
  435. MonoDomain *create_domain(const String &p_friendly_name) {
  436. MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL);
  437. if (domain) {
  438. // Workaround to avoid this exception:
  439. // System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system.
  440. // ---> System.ArgumentException: The 'ExeConfigFilename' argument cannot be null.
  441. mono_domain_set_config(domain, ".", "");
  442. }
  443. return domain;
  444. }
  445. String get_exception_name_and_message(MonoException *p_exc) {
  446. String res;
  447. MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
  448. MonoType *type = mono_class_get_type(klass);
  449. char *full_name = mono_type_full_name(type);
  450. res += full_name;
  451. mono_free(full_name);
  452. res += ": ";
  453. MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
  454. MonoString *msg = (MonoString *)property_get_value(prop, (MonoObject *)p_exc, NULL, NULL);
  455. res += GDMonoMarshal::mono_string_to_godot(msg);
  456. return res;
  457. }
  458. void set_exception_message(MonoException *p_exc, String message) {
  459. MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
  460. MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
  461. MonoString *msg = GDMonoMarshal::mono_string_from_godot(message);
  462. void *params[1] = { msg };
  463. property_set_value(prop, (MonoObject *)p_exc, params, NULL);
  464. }
  465. void debug_print_unhandled_exception(MonoException *p_exc) {
  466. print_unhandled_exception(p_exc);
  467. debug_send_unhandled_exception_error(p_exc);
  468. }
  469. void debug_send_unhandled_exception_error(MonoException *p_exc) {
  470. #ifdef DEBUG_ENABLED
  471. if (!ScriptDebugger::get_singleton()) {
  472. #ifdef TOOLS_ENABLED
  473. if (Engine::get_singleton()->is_editor_hint()) {
  474. ERR_PRINTS(GDMonoUtils::get_exception_name_and_message(p_exc));
  475. }
  476. #endif
  477. return;
  478. }
  479. _TLS_RECURSION_GUARD_;
  480. ScriptLanguage::StackInfo separator;
  481. separator.file = String();
  482. separator.func = "--- " + RTR("End of inner exception stack trace") + " ---";
  483. separator.line = 0;
  484. Vector<ScriptLanguage::StackInfo> si;
  485. String exc_msg;
  486. while (p_exc != NULL) {
  487. GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace);
  488. MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr());
  489. MonoBoolean need_file_info = true;
  490. void *ctor_args[2] = { p_exc, &need_file_info };
  491. MonoException *unexpected_exc = NULL;
  492. CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc);
  493. if (unexpected_exc) {
  494. GDMonoInternals::unhandled_exception(unexpected_exc);
  495. return;
  496. }
  497. Vector<ScriptLanguage::StackInfo> _si;
  498. if (stack_trace != NULL) {
  499. _si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace);
  500. for (int i = _si.size() - 1; i >= 0; i--)
  501. si.insert(0, _si[i]);
  502. }
  503. exc_msg += (exc_msg.length() > 0 ? " ---> " : "") + GDMonoUtils::get_exception_name_and_message(p_exc);
  504. GDMonoClass *exc_class = GDMono::get_singleton()->get_class(mono_get_exception_class());
  505. GDMonoProperty *inner_exc_prop = exc_class->get_property("InnerException");
  506. CRASH_COND(inner_exc_prop == NULL);
  507. MonoObject *inner_exc = inner_exc_prop->get_value((MonoObject *)p_exc);
  508. if (inner_exc != NULL)
  509. si.insert(0, separator);
  510. p_exc = (MonoException *)inner_exc;
  511. }
  512. String file = si.size() ? si[0].file : __FILE__;
  513. String func = si.size() ? si[0].func : FUNCTION_STR;
  514. int line = si.size() ? si[0].line : __LINE__;
  515. String error_msg = "Unhandled exception";
  516. ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si);
  517. #endif
  518. }
  519. void debug_unhandled_exception(MonoException *p_exc) {
  520. GDMonoInternals::unhandled_exception(p_exc); // prints the exception as well
  521. }
  522. void print_unhandled_exception(MonoException *p_exc) {
  523. mono_print_unhandled_exception((MonoObject *)p_exc);
  524. }
  525. void set_pending_exception(MonoException *p_exc) {
  526. #ifdef NO_PENDING_EXCEPTIONS
  527. debug_unhandled_exception(p_exc);
  528. #else
  529. if (get_runtime_invoke_count() == 0) {
  530. debug_unhandled_exception(p_exc);
  531. }
  532. if (!mono_runtime_set_pending_exception(p_exc, false)) {
  533. ERR_PRINTS("Exception thrown from managed code, but it could not be set as pending:");
  534. GDMonoUtils::debug_print_unhandled_exception(p_exc);
  535. }
  536. #endif
  537. }
  538. _THREAD_LOCAL_(int)
  539. current_invoke_count = 0;
  540. MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc) {
  541. GD_MONO_BEGIN_RUNTIME_INVOKE;
  542. MonoObject *ret = mono_runtime_invoke(p_method, p_obj, p_params, (MonoObject **)r_exc);
  543. GD_MONO_END_RUNTIME_INVOKE;
  544. return ret;
  545. }
  546. MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc) {
  547. GD_MONO_BEGIN_RUNTIME_INVOKE;
  548. MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)r_exc);
  549. GD_MONO_END_RUNTIME_INVOKE;
  550. return ret;
  551. }
  552. MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc) {
  553. GD_MONO_BEGIN_RUNTIME_INVOKE;
  554. MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)r_exc);
  555. GD_MONO_END_RUNTIME_INVOKE;
  556. return ret;
  557. }
  558. void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
  559. GD_MONO_BEGIN_RUNTIME_INVOKE;
  560. mono_property_set_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
  561. GD_MONO_END_RUNTIME_INVOKE;
  562. }
  563. MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
  564. GD_MONO_BEGIN_RUNTIME_INVOKE;
  565. MonoObject *ret = mono_property_get_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
  566. GD_MONO_END_RUNTIME_INVOKE;
  567. return ret;
  568. }
  569. uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error) {
  570. r_error = false;
  571. switch (mono_type_get_type(p_enum_basetype)) {
  572. case MONO_TYPE_BOOLEAN:
  573. return (bool)GDMonoMarshal::unbox<MonoBoolean>(p_boxed) ? 1 : 0;
  574. case MONO_TYPE_CHAR:
  575. return GDMonoMarshal::unbox<uint16_t>(p_boxed);
  576. case MONO_TYPE_U1:
  577. return GDMonoMarshal::unbox<uint8_t>(p_boxed);
  578. case MONO_TYPE_U2:
  579. return GDMonoMarshal::unbox<uint16_t>(p_boxed);
  580. case MONO_TYPE_U4:
  581. return GDMonoMarshal::unbox<uint32_t>(p_boxed);
  582. case MONO_TYPE_U8:
  583. return GDMonoMarshal::unbox<uint64_t>(p_boxed);
  584. case MONO_TYPE_I1:
  585. return GDMonoMarshal::unbox<int8_t>(p_boxed);
  586. case MONO_TYPE_I2:
  587. return GDMonoMarshal::unbox<int16_t>(p_boxed);
  588. case MONO_TYPE_I4:
  589. return GDMonoMarshal::unbox<int32_t>(p_boxed);
  590. case MONO_TYPE_I8:
  591. return GDMonoMarshal::unbox<int64_t>(p_boxed);
  592. default:
  593. r_error = true;
  594. return 0;
  595. }
  596. }
  597. void dispose(MonoObject *p_mono_object, MonoException **r_exc) {
  598. invoke_method_thunk(CACHED_METHOD_THUNK(GodotObject, Dispose), p_mono_object, r_exc);
  599. }
  600. namespace Marshal {
  601. #ifdef MONO_GLUE_ENABLED
  602. #ifdef TOOLS_ENABLED
  603. #define NO_GLUE_RET(m_ret) \
  604. { \
  605. if (!mono_cache.godot_api_cache_updated) return m_ret; \
  606. }
  607. #else
  608. #define NO_GLUE_RET(m_ret) \
  609. {}
  610. #endif
  611. #else
  612. #define NO_GLUE_RET(m_ret) \
  613. { return m_ret; }
  614. #endif
  615. bool type_is_generic_array(MonoReflectionType *p_reftype) {
  616. NO_GLUE_RET(false);
  617. TypeIsGenericArray thunk = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
  618. MonoException *exc = NULL;
  619. MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
  620. UNHANDLED_EXCEPTION(exc);
  621. return (bool)res;
  622. }
  623. bool type_is_generic_dictionary(MonoReflectionType *p_reftype) {
  624. NO_GLUE_RET(false);
  625. TypeIsGenericDictionary thunk = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
  626. MonoException *exc = NULL;
  627. MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
  628. UNHANDLED_EXCEPTION(exc);
  629. return (bool)res;
  630. }
  631. void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) {
  632. ArrayGetElementType thunk = CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType);
  633. MonoException *exc = NULL;
  634. invoke_method_thunk(thunk, p_array_reftype, r_elem_reftype, &exc);
  635. UNHANDLED_EXCEPTION(exc);
  636. }
  637. void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
  638. DictionaryGetKeyValueTypes thunk = CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes);
  639. MonoException *exc = NULL;
  640. invoke_method_thunk(thunk, p_dict_reftype, r_key_reftype, r_value_reftype, &exc);
  641. UNHANDLED_EXCEPTION(exc);
  642. }
  643. bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) {
  644. NO_GLUE_RET(false);
  645. GenericIEnumerableIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType);
  646. MonoException *exc = NULL;
  647. MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
  648. UNHANDLED_EXCEPTION(exc);
  649. return (bool)res;
  650. }
  651. bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) {
  652. NO_GLUE_RET(false);
  653. GenericIDictionaryIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType);
  654. MonoException *exc = NULL;
  655. MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
  656. UNHANDLED_EXCEPTION(exc);
  657. return (bool)res;
  658. }
  659. bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) {
  660. NO_GLUE_RET(false);
  661. GenericIEnumerableIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info);
  662. MonoException *exc = NULL;
  663. MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_elem_reftype, &exc);
  664. UNHANDLED_EXCEPTION(exc);
  665. return (bool)res;
  666. }
  667. bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
  668. NO_GLUE_RET(false);
  669. GenericIDictionaryIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info);
  670. MonoException *exc = NULL;
  671. MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_key_reftype, r_value_reftype, &exc);
  672. UNHANDLED_EXCEPTION(exc);
  673. return (bool)res;
  674. }
  675. Array enumerable_to_array(MonoObject *p_enumerable) {
  676. NO_GLUE_RET(Array());
  677. Array result;
  678. EnumerableToArray thunk = CACHED_METHOD_THUNK(MarshalUtils, EnumerableToArray);
  679. MonoException *exc = NULL;
  680. invoke_method_thunk(thunk, p_enumerable, &result, &exc);
  681. UNHANDLED_EXCEPTION(exc);
  682. return result;
  683. }
  684. Dictionary idictionary_to_dictionary(MonoObject *p_idictionary) {
  685. NO_GLUE_RET(Dictionary());
  686. Dictionary result;
  687. IDictionaryToDictionary thunk = CACHED_METHOD_THUNK(MarshalUtils, IDictionaryToDictionary);
  688. MonoException *exc = NULL;
  689. invoke_method_thunk(thunk, p_idictionary, &result, &exc);
  690. UNHANDLED_EXCEPTION(exc);
  691. return result;
  692. }
  693. Dictionary generic_idictionary_to_dictionary(MonoObject *p_generic_idictionary) {
  694. NO_GLUE_RET(Dictionary());
  695. Dictionary result;
  696. GenericIDictionaryToDictionary thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryToDictionary);
  697. MonoException *exc = NULL;
  698. invoke_method_thunk(thunk, p_generic_idictionary, &result, &exc);
  699. UNHANDLED_EXCEPTION(exc);
  700. return result;
  701. }
  702. GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype) {
  703. NO_GLUE_RET(NULL);
  704. MakeGenericArrayType thunk = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericArrayType);
  705. MonoException *exc = NULL;
  706. MonoReflectionType *reftype = invoke_method_thunk(thunk, p_elem_reftype, &exc);
  707. UNHANDLED_EXCEPTION(exc);
  708. return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
  709. }
  710. GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) {
  711. NO_GLUE_RET(NULL);
  712. MakeGenericDictionaryType thunk = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericDictionaryType);
  713. MonoException *exc = NULL;
  714. MonoReflectionType *reftype = invoke_method_thunk(thunk, p_key_reftype, p_value_reftype, &exc);
  715. UNHANDLED_EXCEPTION(exc);
  716. return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
  717. }
  718. } // namespace Marshal
  719. } // namespace GDMonoUtils