gd_mono_utils.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  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-2018 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2018 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 "os/dir_access.h"
  33. #include "os/os.h"
  34. #include "project_settings.h"
  35. #include "reference.h"
  36. #include "../csharp_script.h"
  37. #include "../utils/macros.h"
  38. #include "gd_mono.h"
  39. #include "gd_mono_class.h"
  40. #include "gd_mono_marshal.h"
  41. namespace GDMonoUtils {
  42. MonoCache mono_cache;
  43. #define CACHE_AND_CHECK(m_var, m_val) \
  44. { \
  45. m_var = m_val; \
  46. if (!m_var) { \
  47. ERR_EXPLAIN("Mono Cache: Member " #m_var " is null"); \
  48. ERR_FAIL(); \
  49. } \
  50. }
  51. #define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_class, m_val)
  52. #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)
  53. #define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val)
  54. #define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
  55. #define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val)
  56. #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)
  57. void MonoCache::clear_members() {
  58. class_MonoObject = NULL;
  59. class_bool = NULL;
  60. class_int8_t = NULL;
  61. class_int16_t = NULL;
  62. class_int32_t = NULL;
  63. class_int64_t = NULL;
  64. class_uint8_t = NULL;
  65. class_uint16_t = NULL;
  66. class_uint32_t = NULL;
  67. class_uint64_t = NULL;
  68. class_float = NULL;
  69. class_double = NULL;
  70. class_String = NULL;
  71. class_IntPtr = NULL;
  72. #ifdef DEBUG_ENABLED
  73. class_System_Diagnostics_StackTrace = NULL;
  74. methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL;
  75. method_System_Diagnostics_StackTrace_ctor_bool = NULL;
  76. method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL;
  77. #endif
  78. class_KeyNotFoundException = NULL;
  79. rawclass_Dictionary = NULL;
  80. class_Vector2 = NULL;
  81. class_Rect2 = NULL;
  82. class_Transform2D = NULL;
  83. class_Vector3 = NULL;
  84. class_Basis = NULL;
  85. class_Quat = NULL;
  86. class_Transform = NULL;
  87. class_AABB = NULL;
  88. class_Color = NULL;
  89. class_Plane = NULL;
  90. class_NodePath = NULL;
  91. class_RID = NULL;
  92. class_GodotObject = NULL;
  93. class_GodotReference = NULL;
  94. class_Node = NULL;
  95. class_Control = NULL;
  96. class_Spatial = NULL;
  97. class_WeakRef = NULL;
  98. class_Array = NULL;
  99. class_Dictionary = NULL;
  100. class_MarshalUtils = NULL;
  101. #ifdef DEBUG_ENABLED
  102. class_DebuggingUtils = NULL;
  103. methodthunk_DebuggingUtils_GetStackFrameInfo = NULL;
  104. #endif
  105. class_ExportAttribute = NULL;
  106. field_ExportAttribute_hint = NULL;
  107. field_ExportAttribute_hintString = NULL;
  108. class_SignalAttribute = NULL;
  109. class_ToolAttribute = NULL;
  110. class_RemoteAttribute = NULL;
  111. class_SyncAttribute = NULL;
  112. class_MasterAttribute = NULL;
  113. class_SlaveAttribute = NULL;
  114. class_RemoteSyncAttribute = NULL;
  115. class_MasterSyncAttribute = NULL;
  116. class_SlaveSyncAttribute = NULL;
  117. class_GodotMethodAttribute = NULL;
  118. field_GodotMethodAttribute_methodName = NULL;
  119. field_GodotObject_ptr = NULL;
  120. field_NodePath_ptr = NULL;
  121. field_Image_ptr = NULL;
  122. field_RID_ptr = NULL;
  123. methodthunk_Array_GetPtr = NULL;
  124. methodthunk_Dictionary_GetPtr = NULL;
  125. methodthunk_MarshalUtils_IsArrayGenericType = NULL;
  126. methodthunk_MarshalUtils_IsDictionaryGenericType = NULL;
  127. methodthunk_SignalAwaiter_SignalCallback = NULL;
  128. methodthunk_SignalAwaiter_FailureCallback = NULL;
  129. methodthunk_GodotTaskScheduler_Activate = NULL;
  130. task_scheduler_handle = Ref<MonoGCHandle>();
  131. }
  132. void MonoCache::cleanup() {
  133. corlib_cache_updated = false;
  134. godot_api_cache_updated = false;
  135. }
  136. #define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
  137. void update_corlib_cache() {
  138. CACHE_CLASS_AND_CHECK(MonoObject, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_object_class()));
  139. CACHE_CLASS_AND_CHECK(bool, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_boolean_class()));
  140. CACHE_CLASS_AND_CHECK(int8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_sbyte_class()));
  141. CACHE_CLASS_AND_CHECK(int16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int16_class()));
  142. CACHE_CLASS_AND_CHECK(int32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int32_class()));
  143. CACHE_CLASS_AND_CHECK(int64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int64_class()));
  144. CACHE_CLASS_AND_CHECK(uint8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_byte_class()));
  145. CACHE_CLASS_AND_CHECK(uint16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint16_class()));
  146. CACHE_CLASS_AND_CHECK(uint32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint32_class()));
  147. CACHE_CLASS_AND_CHECK(uint64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint64_class()));
  148. CACHE_CLASS_AND_CHECK(float, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_single_class()));
  149. CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class()));
  150. CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
  151. CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
  152. #ifdef DEBUG_ENABLED
  153. CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace"));
  154. CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_thunk("GetFrames"));
  155. CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true));
  156. 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));
  157. #endif
  158. CACHE_CLASS_AND_CHECK(KeyNotFoundException, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections.Generic", "KeyNotFoundException"));
  159. mono_cache.corlib_cache_updated = true;
  160. }
  161. void update_godot_api_cache() {
  162. CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2));
  163. CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2));
  164. CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D));
  165. CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3));
  166. CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
  167. CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat));
  168. CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform));
  169. CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB));
  170. CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
  171. CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
  172. CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath));
  173. CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(RID));
  174. CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object));
  175. CACHE_CLASS_AND_CHECK(GodotReference, GODOT_API_CLASS(Reference));
  176. CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
  177. CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
  178. CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
  179. CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
  180. CACHE_CLASS_AND_CHECK(Array, GODOT_API_CLASS(Array));
  181. CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_CLASS(Dictionary));
  182. CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
  183. #ifdef DEBUG_ENABLED
  184. CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils));
  185. #endif
  186. // Attributes
  187. CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
  188. CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
  189. CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString"));
  190. CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute));
  191. CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
  192. CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute));
  193. CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute));
  194. CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute));
  195. CACHE_CLASS_AND_CHECK(SlaveAttribute, GODOT_API_CLASS(SlaveAttribute));
  196. CACHE_CLASS_AND_CHECK(RemoteSyncAttribute, GODOT_API_CLASS(RemoteSyncAttribute));
  197. CACHE_CLASS_AND_CHECK(MasterSyncAttribute, GODOT_API_CLASS(MasterSyncAttribute));
  198. CACHE_CLASS_AND_CHECK(SlaveSyncAttribute, GODOT_API_CLASS(SlaveSyncAttribute));
  199. CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
  200. CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
  201. CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD));
  202. CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD));
  203. CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD));
  204. CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_CLASS(Array)->get_method_thunk("GetPtr", 0));
  205. CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_CLASS(Dictionary)->get_method_thunk("GetPtr", 0));
  206. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsArrayGenericType, (IsArrayGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsArrayGenericType", 1));
  207. CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsDictionaryGenericType, (IsDictionaryGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsDictionaryGenericType", 1));
  208. CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("SignalCallback", 1));
  209. CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("FailureCallback", 0));
  210. CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method_thunk("Activate", 0));
  211. #ifdef DEBUG_ENABLED
  212. CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method_thunk("GetStackFrameInfo", 4));
  213. #endif
  214. // TODO Move to CSharpLanguage::init()
  215. MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
  216. GDMonoUtils::runtime_object_init(task_scheduler);
  217. mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
  218. mono_cache.godot_api_cache_updated = true;
  219. }
  220. void clear_cache() {
  221. mono_cache.cleanup();
  222. mono_cache.clear_members();
  223. }
  224. MonoObject *unmanaged_get_managed(Object *unmanaged) {
  225. if (unmanaged) {
  226. if (unmanaged->get_script_instance()) {
  227. CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance());
  228. if (cs_instance) {
  229. return cs_instance->get_mono_object();
  230. }
  231. }
  232. // Only called if the owner does not have a CSharpInstance
  233. void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
  234. if (data) {
  235. return ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->value()->get_target();
  236. }
  237. }
  238. return NULL;
  239. }
  240. void set_main_thread(MonoThread *p_thread) {
  241. mono_thread_set_main(p_thread);
  242. }
  243. void attach_current_thread() {
  244. ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
  245. MonoThread *mono_thread = mono_thread_attach(SCRIPTS_DOMAIN);
  246. ERR_FAIL_NULL(mono_thread);
  247. }
  248. void detach_current_thread() {
  249. ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
  250. MonoThread *mono_thread = mono_thread_current();
  251. ERR_FAIL_NULL(mono_thread);
  252. mono_thread_detach(mono_thread);
  253. }
  254. MonoThread *get_current_thread() {
  255. return mono_thread_current();
  256. }
  257. void runtime_object_init(MonoObject *p_this_obj) {
  258. GD_MONO_BEGIN_RUNTIME_INVOKE;
  259. mono_runtime_object_init(p_this_obj);
  260. GD_MONO_END_RUNTIME_INVOKE;
  261. }
  262. GDMonoClass *get_object_class(MonoObject *p_object) {
  263. return GDMono::get_singleton()->get_class(mono_object_get_class(p_object));
  264. }
  265. GDMonoClass *type_get_proxy_class(const StringName &p_type) {
  266. String class_name = p_type;
  267. if (class_name[0] == '_')
  268. class_name = class_name.substr(1, class_name.length());
  269. GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
  270. #ifdef TOOLS_ENABLED
  271. if (!klass) {
  272. return GDMono::get_singleton()->get_editor_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
  273. }
  274. #endif
  275. return klass;
  276. }
  277. GDMonoClass *get_class_native_base(GDMonoClass *p_class) {
  278. GDMonoClass *klass = p_class;
  279. do {
  280. const GDMonoAssembly *assembly = klass->get_assembly();
  281. if (assembly == GDMono::get_singleton()->get_core_api_assembly())
  282. return klass;
  283. #ifdef TOOLS_ENABLED
  284. if (assembly == GDMono::get_singleton()->get_editor_api_assembly())
  285. return klass;
  286. #endif
  287. } while ((klass = klass->get_parent_class()) != NULL);
  288. return NULL;
  289. }
  290. MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) {
  291. String object_type = p_object->get_class_name();
  292. if (object_type[0] == '_')
  293. object_type = object_type.substr(1, object_type.length());
  294. if (!ClassDB::is_parent_class(object_type, p_native)) {
  295. ERR_EXPLAIN("Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'");
  296. ERR_FAIL_V(NULL);
  297. }
  298. MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
  299. ERR_FAIL_NULL_V(mono_object, NULL);
  300. CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
  301. // Construct
  302. GDMonoUtils::runtime_object_init(mono_object);
  303. return mono_object;
  304. }
  305. MonoObject *create_managed_from(const NodePath &p_from) {
  306. MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(NodePath));
  307. ERR_FAIL_NULL_V(mono_object, NULL);
  308. // Construct
  309. GDMonoUtils::runtime_object_init(mono_object);
  310. CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
  311. return mono_object;
  312. }
  313. MonoObject *create_managed_from(const RID &p_from) {
  314. MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(RID));
  315. ERR_FAIL_NULL_V(mono_object, NULL);
  316. // Construct
  317. GDMonoUtils::runtime_object_init(mono_object);
  318. CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
  319. return mono_object;
  320. }
  321. MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) {
  322. MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
  323. ERR_FAIL_NULL_V(mono_object, NULL);
  324. // Search constructor that takes a pointer as parameter
  325. MonoMethod *m;
  326. void *iter = NULL;
  327. while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
  328. if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
  329. MonoMethodSignature *sig = mono_method_signature(m);
  330. void *front = NULL;
  331. if (mono_signature_get_param_count(sig) == 1 &&
  332. mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
  333. break;
  334. }
  335. }
  336. }
  337. CRASH_COND(m == NULL);
  338. Array *new_array = memnew(Array(p_from));
  339. void *args[1] = { &new_array };
  340. MonoException *exc = NULL;
  341. GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
  342. UNLIKELY_UNHANDLED_EXCEPTION(exc);
  343. return mono_object;
  344. }
  345. MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) {
  346. MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
  347. ERR_FAIL_NULL_V(mono_object, NULL);
  348. // Search constructor that takes a pointer as parameter
  349. MonoMethod *m;
  350. void *iter = NULL;
  351. while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
  352. if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
  353. MonoMethodSignature *sig = mono_method_signature(m);
  354. void *front = NULL;
  355. if (mono_signature_get_param_count(sig) == 1 &&
  356. mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
  357. break;
  358. }
  359. }
  360. }
  361. CRASH_COND(m == NULL);
  362. Dictionary *new_dict = memnew(Dictionary(p_from));
  363. void *args[1] = { &new_dict };
  364. MonoException *exc = NULL;
  365. GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
  366. UNLIKELY_UNHANDLED_EXCEPTION(exc);
  367. return mono_object;
  368. }
  369. MonoDomain *create_domain(const String &p_friendly_name) {
  370. MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL);
  371. if (domain) {
  372. // Workaround to avoid this exception:
  373. // System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system.
  374. // ---> System.ArgumentException: The 'ExeConfigFilename' argument cannot be null.
  375. mono_domain_set_config(domain, ".", "");
  376. }
  377. return domain;
  378. }
  379. String get_exception_name_and_message(MonoException *p_exc) {
  380. String res;
  381. MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
  382. MonoType *type = mono_class_get_type(klass);
  383. char *full_name = mono_type_full_name(type);
  384. res += full_name;
  385. mono_free(full_name);
  386. res += ": ";
  387. MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
  388. MonoString *msg = (MonoString *)property_get_value(prop, (MonoObject *)p_exc, NULL, NULL);
  389. res += GDMonoMarshal::mono_string_to_godot(msg);
  390. return res;
  391. }
  392. void set_exception_message(MonoException *p_exc, String message) {
  393. MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
  394. MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
  395. MonoString *msg = GDMonoMarshal::mono_string_from_godot(message);
  396. void *params[1] = { msg };
  397. property_set_value(prop, (MonoObject *)p_exc, params, NULL);
  398. }
  399. void debug_print_unhandled_exception(MonoException *p_exc) {
  400. print_unhandled_exception(p_exc);
  401. debug_send_unhandled_exception_error(p_exc);
  402. }
  403. void debug_send_unhandled_exception_error(MonoException *p_exc) {
  404. #ifdef DEBUG_ENABLED
  405. if (!ScriptDebugger::get_singleton())
  406. return;
  407. _TLS_RECURSION_GUARD_;
  408. ScriptLanguage::StackInfo separator;
  409. separator.file = String();
  410. separator.func = "--- " + RTR("End of inner exception stack trace") + " ---";
  411. separator.line = 0;
  412. Vector<ScriptLanguage::StackInfo> si;
  413. String exc_msg;
  414. while (p_exc != NULL) {
  415. GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace);
  416. MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr());
  417. MonoBoolean need_file_info = true;
  418. void *ctor_args[2] = { p_exc, &need_file_info };
  419. MonoException *unexpected_exc = NULL;
  420. CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc);
  421. if (unexpected_exc) {
  422. GDMonoInternals::unhandled_exception(unexpected_exc);
  423. _UNREACHABLE_();
  424. }
  425. Vector<ScriptLanguage::StackInfo> _si;
  426. if (stack_trace != NULL) {
  427. _si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace);
  428. for (int i = _si.size() - 1; i >= 0; i--)
  429. si.insert(0, _si[i]);
  430. }
  431. exc_msg += (exc_msg.length() > 0 ? " ---> " : "") + GDMonoUtils::get_exception_name_and_message(p_exc);
  432. GDMonoClass *exc_class = GDMono::get_singleton()->get_class(mono_get_exception_class());
  433. GDMonoProperty *inner_exc_prop = exc_class->get_property("InnerException");
  434. CRASH_COND(inner_exc_prop == NULL);
  435. MonoObject *inner_exc = inner_exc_prop->get_value((MonoObject *)p_exc);
  436. if (inner_exc != NULL)
  437. si.insert(0, separator);
  438. p_exc = (MonoException *)inner_exc;
  439. }
  440. String file = si.size() ? si[0].file : __FILE__;
  441. String func = si.size() ? si[0].func : FUNCTION_STR;
  442. int line = si.size() ? si[0].line : __LINE__;
  443. String error_msg = "Unhandled exception";
  444. ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si);
  445. #endif
  446. }
  447. void debug_unhandled_exception(MonoException *p_exc) {
  448. #ifdef DEBUG_ENABLED
  449. GDMonoUtils::debug_send_unhandled_exception_error(p_exc);
  450. if (ScriptDebugger::get_singleton())
  451. ScriptDebugger::get_singleton()->idle_poll();
  452. #endif
  453. GDMonoInternals::unhandled_exception(p_exc); // prints the exception as well
  454. _UNREACHABLE_();
  455. }
  456. void print_unhandled_exception(MonoException *p_exc) {
  457. mono_print_unhandled_exception((MonoObject *)p_exc);
  458. }
  459. void set_pending_exception(MonoException *p_exc) {
  460. #ifdef HAS_PENDING_EXCEPTIONS
  461. if (get_runtime_invoke_count() == 0) {
  462. debug_unhandled_exception(p_exc);
  463. _UNREACHABLE_();
  464. }
  465. if (!mono_runtime_set_pending_exception(p_exc, false)) {
  466. ERR_PRINTS("Exception thrown from managed code, but it could not be set as pending:");
  467. GDMonoUtils::debug_print_unhandled_exception(p_exc);
  468. }
  469. #else
  470. debug_unhandled_exception(p_exc);
  471. _UNREACHABLE_();
  472. #endif
  473. }
  474. _THREAD_LOCAL_(int)
  475. current_invoke_count = 0;
  476. MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **p_exc) {
  477. GD_MONO_BEGIN_RUNTIME_INVOKE;
  478. MonoObject *ret = mono_runtime_invoke(p_method, p_obj, p_params, (MonoObject **)p_exc);
  479. GD_MONO_END_RUNTIME_INVOKE;
  480. return ret;
  481. }
  482. MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **p_exc) {
  483. GD_MONO_BEGIN_RUNTIME_INVOKE;
  484. MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)p_exc);
  485. GD_MONO_END_RUNTIME_INVOKE;
  486. return ret;
  487. }
  488. MonoString *object_to_string(MonoObject *p_obj, MonoException **p_exc) {
  489. GD_MONO_BEGIN_RUNTIME_INVOKE;
  490. MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)p_exc);
  491. GD_MONO_END_RUNTIME_INVOKE;
  492. return ret;
  493. }
  494. void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc) {
  495. GD_MONO_BEGIN_RUNTIME_INVOKE;
  496. mono_property_set_value(p_prop, p_obj, p_params, (MonoObject **)p_exc);
  497. GD_MONO_END_RUNTIME_INVOKE;
  498. }
  499. MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc) {
  500. GD_MONO_BEGIN_RUNTIME_INVOKE;
  501. MonoObject *ret = mono_property_get_value(p_prop, p_obj, p_params, (MonoObject **)p_exc);
  502. GD_MONO_END_RUNTIME_INVOKE;
  503. return ret;
  504. }
  505. } // namespace GDMonoUtils