| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  gd_mono_utils.cpp                                                    */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-01 14:40:08 +01:00
										 |  |  | /* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | #include "gd_mono_utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "os/dir_access.h"
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | #include "os/os.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | #include "project_settings.h"
 | 
					
						
							|  |  |  | #include "reference.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../csharp_script.h"
 | 
					
						
							|  |  |  | #include "gd_mono.h"
 | 
					
						
							|  |  |  | #include "gd_mono_class.h"
 | 
					
						
							|  |  |  | #include "gd_mono_marshal.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace GDMonoUtils { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MonoCache mono_cache; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-12 19:23:11 +01:00
										 |  |  | #define CACHE_AND_CHECK(m_var, m_val)                             \
 | 
					
						
							|  |  |  | 	{                                                             \ | 
					
						
							|  |  |  | 		m_var = m_val;                                            \ | 
					
						
							|  |  |  | 		if (!m_var) {                                             \ | 
					
						
							|  |  |  | 			ERR_EXPLAIN("Mono Cache: Member " #m_var " is null"); \ | 
					
						
							|  |  |  | 			ERR_FAIL();                                           \ | 
					
						
							|  |  |  | 		}                                                         \ | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_class, m_val)
 | 
					
						
							|  |  |  | #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)
 | 
					
						
							|  |  |  | #define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val)
 | 
					
						
							|  |  |  | #define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | #define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val)
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | #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)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MonoCache::clear_members() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class_MonoObject = NULL; | 
					
						
							|  |  |  | 	class_bool = NULL; | 
					
						
							|  |  |  | 	class_int8_t = NULL; | 
					
						
							|  |  |  | 	class_int16_t = NULL; | 
					
						
							|  |  |  | 	class_int32_t = NULL; | 
					
						
							|  |  |  | 	class_int64_t = NULL; | 
					
						
							|  |  |  | 	class_uint8_t = NULL; | 
					
						
							|  |  |  | 	class_uint16_t = NULL; | 
					
						
							|  |  |  | 	class_uint32_t = NULL; | 
					
						
							|  |  |  | 	class_uint64_t = NULL; | 
					
						
							|  |  |  | 	class_float = NULL; | 
					
						
							|  |  |  | 	class_double = NULL; | 
					
						
							|  |  |  | 	class_String = NULL; | 
					
						
							|  |  |  | 	class_IntPtr = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	class_System_Diagnostics_StackTrace = NULL; | 
					
						
							|  |  |  | 	methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL; | 
					
						
							|  |  |  | 	method_System_Diagnostics_StackTrace_ctor_bool = NULL; | 
					
						
							|  |  |  | 	method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	rawclass_Dictionary = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class_Vector2 = NULL; | 
					
						
							|  |  |  | 	class_Rect2 = NULL; | 
					
						
							|  |  |  | 	class_Transform2D = NULL; | 
					
						
							|  |  |  | 	class_Vector3 = NULL; | 
					
						
							|  |  |  | 	class_Basis = NULL; | 
					
						
							|  |  |  | 	class_Quat = NULL; | 
					
						
							|  |  |  | 	class_Transform = NULL; | 
					
						
							| 
									
										
										
										
											2017-11-16 21:09:00 -05:00
										 |  |  | 	class_AABB = NULL; | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	class_Color = NULL; | 
					
						
							|  |  |  | 	class_Plane = NULL; | 
					
						
							|  |  |  | 	class_NodePath = NULL; | 
					
						
							|  |  |  | 	class_RID = NULL; | 
					
						
							|  |  |  | 	class_GodotObject = NULL; | 
					
						
							| 
									
										
										
										
											2017-10-17 14:02:19 +02:00
										 |  |  | 	class_GodotReference = NULL; | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	class_Node = NULL; | 
					
						
							|  |  |  | 	class_Control = NULL; | 
					
						
							|  |  |  | 	class_Spatial = NULL; | 
					
						
							|  |  |  | 	class_WeakRef = NULL; | 
					
						
							|  |  |  | 	class_MarshalUtils = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	class_DebuggingUtils = NULL; | 
					
						
							|  |  |  | 	methodthunk_DebuggingUtils_GetStackFrameInfo = NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	class_ExportAttribute = NULL; | 
					
						
							|  |  |  | 	field_ExportAttribute_hint = NULL; | 
					
						
							| 
									
										
										
										
											2017-12-24 03:17:48 +01:00
										 |  |  | 	field_ExportAttribute_hintString = NULL; | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	class_ToolAttribute = NULL; | 
					
						
							|  |  |  | 	class_RemoteAttribute = NULL; | 
					
						
							|  |  |  | 	class_SyncAttribute = NULL; | 
					
						
							|  |  |  | 	class_MasterAttribute = NULL; | 
					
						
							|  |  |  | 	class_SlaveAttribute = NULL; | 
					
						
							|  |  |  | 	class_GodotMethodAttribute = NULL; | 
					
						
							|  |  |  | 	field_GodotMethodAttribute_methodName = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	field_GodotObject_ptr = NULL; | 
					
						
							|  |  |  | 	field_NodePath_ptr = NULL; | 
					
						
							|  |  |  | 	field_Image_ptr = NULL; | 
					
						
							|  |  |  | 	field_RID_ptr = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	methodthunk_MarshalUtils_DictionaryToArrays = NULL; | 
					
						
							|  |  |  | 	methodthunk_MarshalUtils_ArraysToDictionary = NULL; | 
					
						
							| 
									
										
										
										
											2017-10-16 03:54:23 +02:00
										 |  |  | 	methodthunk_SignalAwaiter_SignalCallback = NULL; | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	methodthunk_SignalAwaiter_FailureCallback = NULL; | 
					
						
							|  |  |  | 	methodthunk_GodotTaskScheduler_Activate = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	task_scheduler_handle = Ref<MonoGCHandle>(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-12 19:23:11 +01:00
										 |  |  | void MonoCache::cleanup() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	corlib_cache_updated = false; | 
					
						
							|  |  |  | 	godot_api_cache_updated = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | #define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void update_corlib_cache() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(MonoObject, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_object_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(bool, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_boolean_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(int8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_sbyte_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(int16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int16_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(int32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int32_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(int64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int64_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(uint8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_byte_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(uint16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint16_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(uint32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint32_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(uint64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint64_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(float, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_single_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class())); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class())); | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace")); | 
					
						
							|  |  |  | 	CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method("GetFrames")->get_thunk()); | 
					
						
							|  |  |  | 	CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true)); | 
					
						
							|  |  |  | 	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)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-01-12 19:23:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mono_cache.corlib_cache_updated = true; | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void update_godot_api_cache() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform)); | 
					
						
							| 
									
										
										
										
											2017-11-16 21:09:00 -05:00
										 |  |  | 	CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB)); | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath)); | 
					
						
							| 
									
										
										
										
											2018-01-22 14:01:20 +01:00
										 |  |  | 	CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(RID)); | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object)); | 
					
						
							| 
									
										
										
										
											2017-10-17 14:02:19 +02:00
										 |  |  | 	CACHE_CLASS_AND_CHECK(GodotReference, GODOT_API_CLASS(Reference)); | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	// Attributes
 | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute)); | 
					
						
							|  |  |  | 	CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint")); | 
					
						
							| 
									
										
										
										
											2017-12-24 03:17:48 +01:00
										 |  |  | 	CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString")); | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(SlaveAttribute, GODOT_API_CLASS(SlaveAttribute)); | 
					
						
							|  |  |  | 	CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute)); | 
					
						
							|  |  |  | 	CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD)); | 
					
						
							|  |  |  | 	CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD)); | 
					
						
							|  |  |  | 	CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryToArrays, (MarshalUtils_DictToArrays)CACHED_CLASS(MarshalUtils)->get_method("DictionaryToArrays", 3)->get_thunk()); | 
					
						
							|  |  |  | 	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArraysToDictionary, (MarshalUtils_ArraysToDict)CACHED_CLASS(MarshalUtils)->get_method("ArraysToDictionary", 2)->get_thunk()); | 
					
						
							| 
									
										
										
										
											2017-10-16 03:54:23 +02:00
										 |  |  | 	CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1)->get_thunk()); | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk()); | 
					
						
							|  |  |  | 	CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk()); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * TODO Right now we only support Dictionary<object, object>. | 
					
						
							|  |  |  | 		 * It would be great if we could support other key/value types | 
					
						
							|  |  |  | 		 * without forcing the user to copy the entries. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		GDMonoMethod *method_get_dict_type = CACHED_CLASS(MarshalUtils)->get_method("GetDictionaryType", 0); | 
					
						
							|  |  |  | 		ERR_FAIL_NULL(method_get_dict_type); | 
					
						
							|  |  |  | 		MonoReflectionType *dict_refl_type = (MonoReflectionType *)method_get_dict_type->invoke(NULL); | 
					
						
							|  |  |  | 		ERR_FAIL_NULL(dict_refl_type); | 
					
						
							|  |  |  | 		MonoType *dict_type = mono_reflection_type_get_type(dict_refl_type); | 
					
						
							|  |  |  | 		ERR_FAIL_NULL(dict_type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CACHE_RAW_MONO_CLASS_AND_CHECK(Dictionary, mono_class_from_mono_type(dict_type)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-04 21:05:46 +01:00
										 |  |  | 	MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr()); | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	mono_runtime_object_init(task_scheduler); | 
					
						
							|  |  |  | 	mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); | 
					
						
							| 
									
										
										
										
											2018-01-12 19:23:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mono_cache.corlib_cache_updated = true; | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void clear_cache() { | 
					
						
							|  |  |  | 	mono_cache.cleanup(); | 
					
						
							|  |  |  | 	mono_cache.clear_members(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MonoObject *unmanaged_get_managed(Object *unmanaged) { | 
					
						
							|  |  |  | 	if (unmanaged) { | 
					
						
							|  |  |  | 		if (unmanaged->get_script_instance()) { | 
					
						
							|  |  |  | 			CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (cs_instance) { | 
					
						
							|  |  |  | 				return cs_instance->get_mono_object(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Only called if the owner does not have a CSharpInstance
 | 
					
						
							|  |  |  | 		void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (data) { | 
					
						
							|  |  |  | 			return ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->value()->get_target(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void set_main_thread(MonoThread *p_thread) { | 
					
						
							|  |  |  | 	mono_thread_set_main(p_thread); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void attach_current_thread() { | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); | 
					
						
							|  |  |  | 	MonoThread *mono_thread = mono_thread_attach(SCRIPTS_DOMAIN); | 
					
						
							|  |  |  | 	ERR_FAIL_NULL(mono_thread); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void detach_current_thread() { | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); | 
					
						
							|  |  |  | 	MonoThread *mono_thread = mono_thread_current(); | 
					
						
							|  |  |  | 	ERR_FAIL_NULL(mono_thread); | 
					
						
							|  |  |  | 	mono_thread_detach(mono_thread); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MonoThread *get_current_thread() { | 
					
						
							|  |  |  | 	return mono_thread_current(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GDMonoClass *get_object_class(MonoObject *p_object) { | 
					
						
							|  |  |  | 	return GDMono::get_singleton()->get_class(mono_object_get_class(p_object)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GDMonoClass *type_get_proxy_class(const StringName &p_type) { | 
					
						
							|  |  |  | 	String class_name = p_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (class_name[0] == '_') | 
					
						
							|  |  |  | 		class_name = class_name.substr(1, class_name.length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GDMonoClass *klass = GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							|  |  |  | 	if (!klass) { | 
					
						
							|  |  |  | 		return GDMono::get_singleton()->get_editor_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return klass; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GDMonoClass *get_class_native_base(GDMonoClass *p_class) { | 
					
						
							|  |  |  | 	GDMonoClass *klass = p_class; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		const GDMonoAssembly *assembly = klass->get_assembly(); | 
					
						
							|  |  |  | 		if (assembly == GDMono::get_singleton()->get_api_assembly()) | 
					
						
							|  |  |  | 			return klass; | 
					
						
							|  |  |  | #ifdef TOOLS_ENABLED
 | 
					
						
							|  |  |  | 		if (assembly == GDMono::get_singleton()->get_editor_api_assembly()) | 
					
						
							|  |  |  | 			return klass; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} while ((klass = klass->get_parent_class()) != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) { | 
					
						
							|  |  |  | 	String object_type = p_object->get_class_name(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (object_type[0] == '_') | 
					
						
							|  |  |  | 		object_type = object_type.substr(1, object_type.length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ClassDB::is_parent_class(object_type, p_native)) { | 
					
						
							|  |  |  | 		ERR_EXPLAIN("Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'"); | 
					
						
							|  |  |  | 		ERR_FAIL_V(NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-04 21:05:46 +01:00
										 |  |  | 	MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr()); | 
					
						
							| 
									
										
										
										
											2017-10-02 23:24:00 +02:00
										 |  |  | 	ERR_FAIL_NULL_V(mono_object, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Construct
 | 
					
						
							|  |  |  | 	mono_runtime_object_init(mono_object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mono_object; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MonoObject *create_managed_from(const NodePath &p_from) { | 
					
						
							|  |  |  | 	MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(NodePath)); | 
					
						
							|  |  |  | 	ERR_FAIL_NULL_V(mono_object, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Construct
 | 
					
						
							|  |  |  | 	mono_runtime_object_init(mono_object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mono_object; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MonoObject *create_managed_from(const RID &p_from) { | 
					
						
							|  |  |  | 	MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(RID)); | 
					
						
							|  |  |  | 	ERR_FAIL_NULL_V(mono_object, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Construct
 | 
					
						
							|  |  |  | 	mono_runtime_object_init(mono_object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mono_object; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MonoDomain *create_domain(const String &p_friendly_name) { | 
					
						
							|  |  |  | 	MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (domain) { | 
					
						
							|  |  |  | 		// Workaround to avoid this exception:
 | 
					
						
							|  |  |  | 		// System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system.
 | 
					
						
							|  |  |  | 		// ---> System.ArgumentException: The 'ExeConfigFilename' argument cannot be null.
 | 
					
						
							|  |  |  | 		mono_domain_set_config(domain, ".", ""); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return domain; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String get_exception_name_and_message(MonoObject *p_ex) { | 
					
						
							|  |  |  | 	String res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MonoClass *klass = mono_object_get_class(p_ex); | 
					
						
							|  |  |  | 	MonoType *type = mono_class_get_type(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	char *full_name = mono_type_full_name(type); | 
					
						
							|  |  |  | 	res += full_name; | 
					
						
							|  |  |  | 	mono_free(full_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res += ": "; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MonoProperty *prop = mono_class_get_property_from_name(klass, "Message"); | 
					
						
							|  |  |  | 	MonoString *msg = (MonoString *)mono_property_get_value(prop, p_ex, NULL, NULL); | 
					
						
							|  |  |  | 	res += GDMonoMarshal::mono_string_to_godot(msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-04 21:05:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | void print_unhandled_exception(MonoObject *p_exc) { | 
					
						
							|  |  |  | 	print_unhandled_exception(p_exc, false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 22:27:55 +01:00
										 |  |  | void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution) { | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | 	mono_print_unhandled_exception(p_exc); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							| 
									
										
										
										
											2018-01-12 19:23:11 +01:00
										 |  |  | 	if (!ScriptDebugger::get_singleton()) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | 	GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); | 
					
						
							|  |  |  | 	MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MonoBoolean need_file_info = true; | 
					
						
							|  |  |  | 	void *ctor_args[2] = { p_exc, &need_file_info }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MonoObject *unexpected_exc = NULL; | 
					
						
							|  |  |  | 	CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (unexpected_exc != NULL) { | 
					
						
							|  |  |  | 		mono_print_unhandled_exception(unexpected_exc); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-09 22:27:55 +01:00
										 |  |  | 		if (p_recursion_caution) { | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | 			// Called from CSharpLanguage::get_current_stack_info,
 | 
					
						
							|  |  |  | 			// so printing an error here could result in endless recursion
 | 
					
						
							|  |  |  | 			OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed"); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ERR_FAIL(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<ScriptLanguage::StackInfo> si; | 
					
						
							| 
									
										
										
										
											2018-01-09 22:27:55 +01:00
										 |  |  | 	if (stack_trace != NULL && !p_recursion_caution) | 
					
						
							| 
									
										
										
										
											2018-01-09 17:19:03 +01:00
										 |  |  | 		si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String file = si.size() ? si[0].file : __FILE__; | 
					
						
							|  |  |  | 	String func = si.size() ? si[0].func : FUNCTION_STR; | 
					
						
							|  |  |  | 	int line = si.size() ? si[0].line : __LINE__; | 
					
						
							|  |  |  | 	String error_msg = "Unhandled exception"; | 
					
						
							|  |  |  | 	String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-01-04 21:05:46 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 21:09:00 -05:00
										 |  |  | } // namespace GDMonoUtils
 |