diff options
Diffstat (limited to 'modules/mono/mono_gd')
-rw-r--r-- | modules/mono/mono_gd/gd_mono.h | 4 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.cpp | 4 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_cache.cpp | 30 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_cache.h | 21 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_field.cpp | 79 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_field.h | 15 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_internals.cpp | 11 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_marshal.cpp | 413 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_marshal.h | 100 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_method.cpp | 64 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_method.h | 26 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_property.h | 14 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_utils.cpp | 57 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_utils.h | 15 |
14 files changed, 685 insertions, 168 deletions
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 306fa15f12..9528c64f8d 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -105,7 +105,7 @@ private: MonoDomain *root_domain; MonoDomain *scripts_domain; - HashMap<uint32_t, HashMap<String, GDMonoAssembly *> > assemblies; + HashMap<uint32_t, HashMap<String, GDMonoAssembly *>> assemblies; GDMonoAssembly *corlib_assembly; GDMonoAssembly *project_assembly; @@ -203,7 +203,7 @@ public: static GDMono *get_singleton() { return singleton; } - GD_NORETURN static void unhandled_exception_hook(MonoObject *p_exc, void *p_user_data); + [[noreturn]] static void unhandled_exception_hook(MonoObject *p_exc, void *p_user_data); UnhandledExceptionPolicy get_unhandled_exception_policy() const { return unhandled_exception_policy; } diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 6cf5377e2c..6da1db249c 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -78,7 +78,7 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin if (p_custom_config.empty()) { r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir()); } else { - String api_config = p_custom_config == "Release" ? "Release" : "Debug"; + String api_config = p_custom_config == "ExportRelease" ? "Release" : "Debug"; r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_base_dir().plus_file(api_config)); } @@ -148,7 +148,7 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d return res ? res->get_assembly() : NULL; } -static _THREAD_LOCAL_(MonoImage *) image_corlib_loading = NULL; +static thread_local MonoImage *image_corlib_loading = NULL; MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, void *user_data, bool refonly) { diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index 0ad90a510e..be0b846702 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -103,15 +103,19 @@ void CachedData::clear_godot_api_cache() { rawclass_Dictionary = NULL; class_Vector2 = NULL; + class_Vector2i = NULL; class_Rect2 = NULL; + class_Rect2i = NULL; class_Transform2D = NULL; class_Vector3 = NULL; + class_Vector3i = NULL; class_Basis = NULL; class_Quat = NULL; class_Transform = NULL; class_AABB = NULL; class_Color = NULL; class_Plane = NULL; + class_StringName = NULL; class_NodePath = NULL; class_RID = NULL; class_GodotObject = NULL; @@ -120,6 +124,8 @@ void CachedData::clear_godot_api_cache() { class_Control = NULL; class_Spatial = NULL; class_WeakRef = NULL; + class_Callable = NULL; + class_SignalInfo = NULL; class_Array = NULL; class_Dictionary = NULL; class_MarshalUtils = NULL; @@ -145,6 +151,7 @@ void CachedData::clear_godot_api_cache() { field_GodotMethodAttribute_methodName = NULL; field_GodotObject_ptr = NULL; + field_StringName_ptr = NULL; field_NodePath_ptr = NULL; field_Image_ptr = NULL; field_RID_ptr = NULL; @@ -153,9 +160,13 @@ void CachedData::clear_godot_api_cache() { methodthunk_Array_GetPtr.nullify(); methodthunk_Dictionary_GetPtr.nullify(); methodthunk_SignalAwaiter_SignalCallback.nullify(); - methodthunk_SignalAwaiter_FailureCallback.nullify(); methodthunk_GodotTaskScheduler_Activate.nullify(); + methodthunk_Delegate_Equals.nullify(); + + methodthunk_DelegateUtils_TrySerializeDelegate.nullify(); + methodthunk_DelegateUtils_TryDeserializeDelegate.nullify(); + // Start of MarshalUtils methods methodthunk_MarshalUtils_TypeIsGenericArray.nullify(); @@ -178,7 +189,7 @@ void CachedData::clear_godot_api_cache() { // End of MarshalUtils methods - task_scheduler_handle = Ref<MonoGCHandle>(); + task_scheduler_handle = Ref<MonoGCHandleRef>(); } #define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class)) @@ -211,6 +222,8 @@ void update_corlib_cache() { 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 + CACHE_METHOD_THUNK_AND_CHECK(Delegate, Equals, GDMono::get_singleton()->get_corlib_assembly()->get_class("System", "Delegate")->get_method_with_desc("System.Delegate:Equals(object)", 1)); + CACHE_CLASS_AND_CHECK(KeyNotFoundException, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections.Generic", "KeyNotFoundException")); cached_data.corlib_cache_updated = true; @@ -219,15 +232,19 @@ void update_corlib_cache() { void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2)); + CACHE_CLASS_AND_CHECK(Vector2i, GODOT_API_CLASS(Vector2i)); CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2)); + CACHE_CLASS_AND_CHECK(Rect2i, GODOT_API_CLASS(Rect2i)); CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D)); CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3)); + CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i)); CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis)); CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat)); CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform)); CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB)); CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color)); CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane)); + CACHE_CLASS_AND_CHECK(StringName, GODOT_API_CLASS(StringName)); CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath)); CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(RID)); CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object)); @@ -236,6 +253,8 @@ void update_godot_api_cache() { 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(Callable, GODOT_API_CLASS(Callable)); + CACHE_CLASS_AND_CHECK(SignalInfo, GODOT_API_CLASS(SignalInfo)); CACHE_CLASS_AND_CHECK(Array, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Array)); CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)); CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils)); @@ -261,6 +280,7 @@ void update_godot_api_cache() { 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(StringName, ptr, CACHED_CLASS(StringName)->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)); @@ -268,9 +288,11 @@ void update_godot_api_cache() { CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Array)->get_method("GetPtr", 0)); CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)->get_method("GetPtr", 0)); CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1)); - CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)); CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)); + CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TrySerializeDelegate, GODOT_API_CLASS(DelegateUtils)->get_method("TrySerializeDelegate", 2)); + CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TryDeserializeDelegate, GODOT_API_CLASS(DelegateUtils)->get_method("TryDeserializeDelegate", 2)); + // Start of MarshalUtils methods CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericArray", 1)); @@ -300,7 +322,7 @@ void update_godot_api_cache() { // TODO Move to CSharpLanguage::init() and do handle disposal MonoObject *task_scheduler = mono_object_new(mono_domain_get(), GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr()); GDMonoUtils::runtime_object_init(task_scheduler, GODOT_API_CLASS(GodotTaskScheduler)); - cached_data.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); + cached_data.task_scheduler_handle = MonoGCHandleRef::create_strong(task_scheduler); cached_data.godot_api_cache_updated = true; } diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 0458e91240..b2dacee67c 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -73,15 +73,19 @@ struct CachedData { // ----------------------------------------------- GDMonoClass *class_Vector2; + GDMonoClass *class_Vector2i; GDMonoClass *class_Rect2; + GDMonoClass *class_Rect2i; GDMonoClass *class_Transform2D; GDMonoClass *class_Vector3; + GDMonoClass *class_Vector3i; GDMonoClass *class_Basis; GDMonoClass *class_Quat; GDMonoClass *class_Transform; GDMonoClass *class_AABB; GDMonoClass *class_Color; GDMonoClass *class_Plane; + GDMonoClass *class_StringName; GDMonoClass *class_NodePath; GDMonoClass *class_RID; GDMonoClass *class_GodotObject; @@ -90,6 +94,8 @@ struct CachedData { GDMonoClass *class_Control; GDMonoClass *class_Spatial; GDMonoClass *class_WeakRef; + GDMonoClass *class_Callable; + GDMonoClass *class_SignalInfo; GDMonoClass *class_Array; GDMonoClass *class_Dictionary; GDMonoClass *class_MarshalUtils; @@ -115,6 +121,7 @@ struct CachedData { GDMonoField *field_GodotMethodAttribute_methodName; GDMonoField *field_GodotObject_ptr; + GDMonoField *field_StringName_ptr; GDMonoField *field_NodePath_ptr; GDMonoField *field_Image_ptr; GDMonoField *field_RID_ptr; @@ -123,9 +130,13 @@ struct CachedData { GDMonoMethodThunkR<Array *, MonoObject *> methodthunk_Array_GetPtr; GDMonoMethodThunkR<Dictionary *, MonoObject *> methodthunk_Dictionary_GetPtr; GDMonoMethodThunk<MonoObject *, MonoArray *> methodthunk_SignalAwaiter_SignalCallback; - GDMonoMethodThunk<MonoObject *> methodthunk_SignalAwaiter_FailureCallback; GDMonoMethodThunk<MonoObject *> methodthunk_GodotTaskScheduler_Activate; + GDMonoMethodThunkR<MonoBoolean, MonoObject *, MonoObject *> methodthunk_Delegate_Equals; + + GDMonoMethodThunkR<MonoBoolean, MonoDelegate *, MonoObject *> methodthunk_DelegateUtils_TrySerializeDelegate; + GDMonoMethodThunkR<MonoBoolean, MonoObject *, MonoDelegate **> methodthunk_DelegateUtils_TryDeserializeDelegate; + // Start of MarshalUtils methods GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericArray; @@ -148,7 +159,7 @@ struct CachedData { // End of MarshalUtils methods - Ref<MonoGCHandle> task_scheduler_handle; + Ref<MonoGCHandleRef> task_scheduler_handle; bool corlib_cache_updated; bool godot_api_cache_updated; @@ -193,10 +204,4 @@ _FORCE_INLINE_ bool tools_godot_api_check() { #define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoCache::cached_data.methodthunk_##m_class##_##m_method) #define CACHED_PROPERTY(m_class, m_property) (GDMonoCache::cached_data.property_##m_class##_##m_property) -#ifdef REAL_T_IS_DOUBLE -#define REAL_T_MONOCLASS CACHED_CLASS_RAW(double) -#else -#define REAL_T_MONOCLASS CACHED_CLASS_RAW(float) -#endif - #endif // GD_MONO_CACHE_H diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index 03b56c9949..11942c47d9 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -37,6 +37,10 @@ #include "gd_mono_marshal.h" #include "gd_mono_utils.h" +void GDMonoField::set_value(MonoObject *p_object, MonoObject *p_value) { + mono_field_set_value(p_object, mono_field, p_value); +} + void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) { mono_field_set_value(p_object, mono_field, &p_ptr); } @@ -128,11 +132,21 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Vector2i)) { + SET_FROM_STRUCT(Vector2i); + break; + } + if (tclass == CACHED_CLASS(Rect2)) { SET_FROM_STRUCT(Rect2); break; } + if (tclass == CACHED_CLASS(Rect2i)) { + SET_FROM_STRUCT(Rect2i); + break; + } + if (tclass == CACHED_CLASS(Transform2D)) { SET_FROM_STRUCT(Transform2D); break; @@ -143,6 +157,11 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Vector3i)) { + SET_FROM_STRUCT(Vector3i); + break; + } + if (tclass == CACHED_CLASS(Basis)) { SET_FROM_STRUCT(Basis); break; @@ -173,6 +192,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Callable)) { + GDMonoMarshal::M_Callable val = GDMonoMarshal::callable_to_managed(p_value.operator Callable()); + mono_field_set_value(p_object, mono_field, &val); + break; + } + + if (tclass == CACHED_CLASS(SignalInfo)) { + GDMonoMarshal::M_SignalInfo val = GDMonoMarshal::signal_info_to_managed(p_value.operator Signal()); + mono_field_set_value(p_object, mono_field, &val); + break; + } + if (mono_class_is_enum(tclass->get_mono_ptr())) { MonoType *enum_basetype = mono_class_enum_basetype(tclass->get_mono_ptr()); switch (mono_type_get_type(enum_basetype)) { @@ -256,11 +287,21 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } - if (array_type->eklass == REAL_T_MONOCLASS) { + if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) { + SET_FROM_ARRAY(PackedInt64Array); + break; + } + + if (array_type->eklass == CACHED_CLASS_RAW(float)) { SET_FROM_ARRAY(PackedFloat32Array); break; } + if (array_type->eklass == CACHED_CLASS_RAW(double)) { + SET_FROM_ARRAY(PackedFloat64Array); + break; + } + if (array_type->eklass == CACHED_CLASS_RAW(String)) { SET_FROM_ARRAY(PackedStringArray); break; @@ -294,6 +335,12 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (CACHED_CLASS(StringName) == type_class) { + MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator StringName()); + mono_field_set_value(p_object, mono_field, managed); + break; + } + if (CACHED_CLASS(NodePath) == type_class) { MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath()); mono_field_set_value(p_object, mono_field, managed); @@ -386,12 +433,21 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ case Variant::VECTOR2: { SET_FROM_STRUCT(Vector2); } break; + case Variant::VECTOR2I: { + SET_FROM_STRUCT(Vector2i); + } break; case Variant::RECT2: { SET_FROM_STRUCT(Rect2); } break; + case Variant::RECT2I: { + SET_FROM_STRUCT(Rect2i); + } break; case Variant::VECTOR3: { SET_FROM_STRUCT(Vector3); } break; + case Variant::VECTOR3I: { + SET_FROM_STRUCT(Vector3i); + } break; case Variant::TRANSFORM2D: { SET_FROM_STRUCT(Transform2D); } break; @@ -413,6 +469,10 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ case Variant::COLOR: { SET_FROM_STRUCT(Color); } break; + case Variant::STRING_NAME: { + MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator StringName()); + mono_field_set_value(p_object, mono_field, managed); + } break; case Variant::NODE_PATH: { MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath()); mono_field_set_value(p_object, mono_field, managed); @@ -424,8 +484,15 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ case Variant::OBJECT: { MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *()); mono_field_set_value(p_object, mono_field, managed); - break; - } + } break; + case Variant::CALLABLE: { + GDMonoMarshal::M_Callable val = GDMonoMarshal::callable_to_managed(p_value.operator Callable()); + mono_field_set_value(p_object, mono_field, &val); + } break; + case Variant::SIGNAL: { + GDMonoMarshal::M_SignalInfo val = GDMonoMarshal::signal_info_to_managed(p_value.operator Signal()); + mono_field_set_value(p_object, mono_field, &val); + } break; case Variant::DICTIONARY: { MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary)); mono_field_set_value(p_object, mono_field, managed); @@ -440,9 +507,15 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ case Variant::PACKED_INT32_ARRAY: { SET_FROM_ARRAY(PackedInt32Array); } break; + case Variant::PACKED_INT64_ARRAY: { + SET_FROM_ARRAY(PackedInt64Array); + } break; case Variant::PACKED_FLOAT32_ARRAY: { SET_FROM_ARRAY(PackedFloat32Array); } break; + case Variant::PACKED_FLOAT64_ARRAY: { + SET_FROM_ARRAY(PackedFloat64Array); + } break; case Variant::PACKED_STRING_ARRAY: { SET_FROM_ARRAY(PackedStringArray); } break; diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index 76ee0963c4..61f2c8f071 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -47,21 +47,22 @@ class GDMonoField : public IMonoClassMember { MonoCustomAttrInfo *attributes; public: - virtual GDMonoClass *get_enclosing_class() const GD_FINAL { return owner; } + virtual GDMonoClass *get_enclosing_class() const final { return owner; } - virtual MemberType get_member_type() const GD_FINAL { return MEMBER_TYPE_FIELD; } + virtual MemberType get_member_type() const final { return MEMBER_TYPE_FIELD; } - virtual StringName get_name() const GD_FINAL { return name; } + virtual StringName get_name() const final { return name; } - virtual bool is_static() GD_FINAL; - virtual Visibility get_visibility() GD_FINAL; + virtual bool is_static() final; + virtual Visibility get_visibility() final; - virtual bool has_attribute(GDMonoClass *p_attr_class) GD_FINAL; - virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) GD_FINAL; + virtual bool has_attribute(GDMonoClass *p_attr_class) final; + virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) final; void fetch_attributes(); _FORCE_INLINE_ ManagedType get_type() const { return type; } + void set_value(MonoObject *p_object, MonoObject *p_value); void set_value_raw(MonoObject *p_object, void *p_ptr); void set_value_from_variant(MonoObject *p_object, const Variant &p_value); diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index b179b484f3..53e642f317 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -33,7 +33,6 @@ #include "../csharp_script.h" #include "../mono_gc_handle.h" #include "../utils/macros.h" -#include "../utils/thread_local.h" #include "gd_mono_class.h" #include "gd_mono_marshal.h" #include "gd_mono_utils.h" @@ -76,7 +75,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { script_binding.inited = true; script_binding.type_name = NATIVE_GDMONOCLASS_NAME(klass); script_binding.wrapper_class = klass; - script_binding.gchandle = ref ? MonoGCHandle::create_weak(managed) : MonoGCHandle::create_strong(managed); + script_binding.gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed); script_binding.owner = unmanaged; if (ref) { @@ -102,15 +101,17 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { return; } - Ref<MonoGCHandle> gchandle = ref ? MonoGCHandle::create_weak(managed) : MonoGCHandle::create_strong(managed); + MonoGCHandleData gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed); Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass, native); CRASH_COND(script.is_null()); - ScriptInstance *si = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle); + CSharpInstance *csharp_instance = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle); - unmanaged->set_script_and_instance(script, si); + unmanaged->set_script_and_instance(script, csharp_instance); + + csharp_instance->connect_event_signals(); } void unhandled_exception(MonoException *p_exc) { diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 695be64d6e..0de5352752 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -30,13 +30,14 @@ #include "gd_mono_marshal.h" +#include "../signal_awaiter_utils.h" #include "gd_mono.h" #include "gd_mono_cache.h" #include "gd_mono_class.h" namespace GDMonoMarshal { -Variant::Type managed_to_variant_type(const ManagedType &p_type) { +Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_variant) { switch (p_type.type_encoding) { case MONO_TYPE_BOOLEAN: return Variant::BOOL; @@ -74,15 +75,24 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { if (vtclass == CACHED_CLASS(Vector2)) return Variant::VECTOR2; + if (vtclass == CACHED_CLASS(Vector2i)) + return Variant::VECTOR2I; + if (vtclass == CACHED_CLASS(Rect2)) return Variant::RECT2; + if (vtclass == CACHED_CLASS(Rect2i)) + return Variant::RECT2I; + if (vtclass == CACHED_CLASS(Transform2D)) return Variant::TRANSFORM2D; if (vtclass == CACHED_CLASS(Vector3)) return Variant::VECTOR3; + if (vtclass == CACHED_CLASS(Vector3i)) + return Variant::VECTOR3I; + if (vtclass == CACHED_CLASS(Basis)) return Variant::BASIS; @@ -101,6 +111,12 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { if (vtclass == CACHED_CLASS(Plane)) return Variant::PLANE; + if (vtclass == CACHED_CLASS(Callable)) + return Variant::CALLABLE; + + if (vtclass == CACHED_CLASS(SignalInfo)) + return Variant::SIGNAL; + if (mono_class_is_enum(vtclass->get_mono_ptr())) return Variant::INT; } break; @@ -118,9 +134,15 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) return Variant::PACKED_INT32_ARRAY; - if (array_type->eklass == REAL_T_MONOCLASS) + if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) + return Variant::PACKED_INT64_ARRAY; + + if (array_type->eklass == CACHED_CLASS_RAW(float)) return Variant::PACKED_FLOAT32_ARRAY; + if (array_type->eklass == CACHED_CLASS_RAW(double)) + return Variant::PACKED_FLOAT64_ARRAY; + if (array_type->eklass == CACHED_CLASS_RAW(String)) return Variant::PACKED_STRING_ARRAY; @@ -142,6 +164,10 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { return Variant::OBJECT; } + if (CACHED_CLASS(StringName) == type_class) { + return Variant::STRING_NAME; + } + if (CACHED_CLASS(NodePath) == type_class) { return Variant::NODE_PATH; } @@ -179,6 +205,12 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { } } break; + case MONO_TYPE_OBJECT: { + if (r_nil_is_variant) + *r_nil_is_variant = true; + return Variant::NIL; + } break; + case MONO_TYPE_GENERICINST: { MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type()); @@ -211,6 +243,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { } break; } + if (r_nil_is_variant) + *r_nil_is_variant = false; + // Unknown return Variant::NIL; } @@ -387,11 +422,21 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector2), &from); } + if (vtclass == CACHED_CLASS(Vector2i)) { + GDMonoMarshal::M_Vector2i from = MARSHALLED_OUT(Vector2i, p_var->operator ::Vector2i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector2i), &from); + } + if (vtclass == CACHED_CLASS(Rect2)) { GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_var->operator ::Rect2()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Rect2), &from); } + if (vtclass == CACHED_CLASS(Rect2i)) { + GDMonoMarshal::M_Rect2i from = MARSHALLED_OUT(Rect2i, p_var->operator ::Rect2i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Rect2i), &from); + } + if (vtclass == CACHED_CLASS(Transform2D)) { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var->operator ::Transform2D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from); @@ -402,6 +447,11 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector3), &from); } + if (vtclass == CACHED_CLASS(Vector3i)) { + GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_var->operator ::Vector3i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector3i), &from); + } + if (vtclass == CACHED_CLASS(Basis)) { GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_var->operator ::Basis()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Basis), &from); @@ -432,6 +482,16 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from); } + if (vtclass == CACHED_CLASS(Callable)) { + GDMonoMarshal::M_Callable from = GDMonoMarshal::callable_to_managed(p_var->operator Callable()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Callable), &from); + } + + if (vtclass == CACHED_CLASS(SignalInfo)) { + GDMonoMarshal::M_SignalInfo from = GDMonoMarshal::signal_info_to_managed(p_var->operator Signal()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(SignalInfo), &from); + } + if (mono_class_is_enum(vtclass->get_mono_ptr())) { MonoType *enum_basetype = mono_class_enum_basetype(vtclass->get_mono_ptr()); MonoClass *enum_baseclass = mono_class_from_mono_type(enum_basetype); @@ -496,9 +556,15 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) return (MonoObject *)PackedInt32Array_to_mono_array(p_var->operator PackedInt32Array()); - if (array_type->eklass == REAL_T_MONOCLASS) + if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) + return (MonoObject *)PackedInt64Array_to_mono_array(p_var->operator PackedInt64Array()); + + if (array_type->eklass == CACHED_CLASS_RAW(float)) return (MonoObject *)PackedFloat32Array_to_mono_array(p_var->operator PackedFloat32Array()); + if (array_type->eklass == CACHED_CLASS_RAW(double)) + return (MonoObject *)PackedFloat64Array_to_mono_array(p_var->operator PackedFloat64Array()); + if (array_type->eklass == CACHED_CLASS_RAW(String)) return (MonoObject *)PackedStringArray_to_mono_array(p_var->operator PackedStringArray()); @@ -522,6 +588,10 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return GDMonoUtils::unmanaged_get_managed(p_var->operator Object *()); } + if (CACHED_CLASS(StringName) == type_class) { + return GDMonoUtils::create_managed_from(p_var->operator StringName()); + } + if (CACHED_CLASS(NodePath) == type_class) { return GDMonoUtils::create_managed_from(p_var->operator NodePath()); } @@ -592,14 +662,26 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_var->operator ::Vector2()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector2), &from); } + case Variant::VECTOR2I: { + GDMonoMarshal::M_Vector2i from = MARSHALLED_OUT(Vector2i, p_var->operator ::Vector2i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector2i), &from); + } case Variant::RECT2: { GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_var->operator ::Rect2()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Rect2), &from); } + case Variant::RECT2I: { + GDMonoMarshal::M_Rect2i from = MARSHALLED_OUT(Rect2i, p_var->operator ::Rect2i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Rect2i), &from); + } case Variant::VECTOR3: { GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_var->operator ::Vector3()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector3), &from); } + case Variant::VECTOR3I: { + GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_var->operator ::Vector3i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector3i), &from); + } case Variant::TRANSFORM2D: { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var->operator ::Transform2D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from); @@ -628,12 +710,22 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var->operator ::Color()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from); } + case Variant::STRING_NAME: + return GDMonoUtils::create_managed_from(p_var->operator StringName()); case Variant::NODE_PATH: return GDMonoUtils::create_managed_from(p_var->operator NodePath()); case Variant::_RID: return GDMonoUtils::create_managed_from(p_var->operator RID()); case Variant::OBJECT: return GDMonoUtils::unmanaged_get_managed(p_var->operator Object *()); + case Variant::CALLABLE: { + GDMonoMarshal::M_Callable from = GDMonoMarshal::callable_to_managed(p_var->operator Callable()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Callable), &from); + } + case Variant::SIGNAL: { + GDMonoMarshal::M_SignalInfo from = GDMonoMarshal::signal_info_to_managed(p_var->operator Signal()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(SignalInfo), &from); + } case Variant::DICTIONARY: return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary)); case Variant::ARRAY: @@ -642,8 +734,12 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return (MonoObject *)PackedByteArray_to_mono_array(p_var->operator PackedByteArray()); case Variant::PACKED_INT32_ARRAY: return (MonoObject *)PackedInt32Array_to_mono_array(p_var->operator PackedInt32Array()); + case Variant::PACKED_INT64_ARRAY: + return (MonoObject *)PackedInt64Array_to_mono_array(p_var->operator PackedInt64Array()); case Variant::PACKED_FLOAT32_ARRAY: return (MonoObject *)PackedFloat32Array_to_mono_array(p_var->operator PackedFloat32Array()); + case Variant::PACKED_FLOAT64_ARRAY: + return (MonoObject *)PackedFloat64Array_to_mono_array(p_var->operator PackedFloat64Array()); case Variant::PACKED_STRING_ARRAY: return (MonoObject *)PackedStringArray_to_mono_array(p_var->operator PackedStringArray()); case Variant::PACKED_VECTOR2_ARRAY: @@ -744,34 +840,49 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type GDMonoClass *vtclass = p_type.type_class; if (vtclass == CACHED_CLASS(Vector2)) - return MARSHALLED_IN(Vector2, (GDMonoMarshal::M_Vector2 *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Vector2, unbox_addr<GDMonoMarshal::M_Vector2>(p_obj)); + + if (vtclass == CACHED_CLASS(Vector2i)) + return MARSHALLED_IN(Vector2i, unbox_addr<GDMonoMarshal::M_Vector2i>(p_obj)); if (vtclass == CACHED_CLASS(Rect2)) - return MARSHALLED_IN(Rect2, (GDMonoMarshal::M_Rect2 *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Rect2, unbox_addr<GDMonoMarshal::M_Rect2>(p_obj)); + + if (vtclass == CACHED_CLASS(Rect2i)) + return MARSHALLED_IN(Rect2i, unbox_addr<GDMonoMarshal::M_Rect2i>(p_obj)); if (vtclass == CACHED_CLASS(Transform2D)) - return MARSHALLED_IN(Transform2D, (GDMonoMarshal::M_Transform2D *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Transform2D, unbox_addr<GDMonoMarshal::M_Transform2D>(p_obj)); if (vtclass == CACHED_CLASS(Vector3)) - return MARSHALLED_IN(Vector3, (GDMonoMarshal::M_Vector3 *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Vector3, unbox_addr<GDMonoMarshal::M_Vector3>(p_obj)); + + if (vtclass == CACHED_CLASS(Vector3i)) + return MARSHALLED_IN(Vector3i, unbox_addr<GDMonoMarshal::M_Vector3i>(p_obj)); if (vtclass == CACHED_CLASS(Basis)) - return MARSHALLED_IN(Basis, (GDMonoMarshal::M_Basis *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Basis, unbox_addr<GDMonoMarshal::M_Basis>(p_obj)); if (vtclass == CACHED_CLASS(Quat)) - return MARSHALLED_IN(Quat, (GDMonoMarshal::M_Quat *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Quat, unbox_addr<GDMonoMarshal::M_Quat>(p_obj)); if (vtclass == CACHED_CLASS(Transform)) - return MARSHALLED_IN(Transform, (GDMonoMarshal::M_Transform *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Transform, unbox_addr<GDMonoMarshal::M_Transform>(p_obj)); if (vtclass == CACHED_CLASS(AABB)) - return MARSHALLED_IN(AABB, (GDMonoMarshal::M_AABB *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(AABB, unbox_addr<GDMonoMarshal::M_AABB>(p_obj)); if (vtclass == CACHED_CLASS(Color)) - return MARSHALLED_IN(Color, (GDMonoMarshal::M_Color *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Color, unbox_addr<GDMonoMarshal::M_Color>(p_obj)); if (vtclass == CACHED_CLASS(Plane)) - return MARSHALLED_IN(Plane, (GDMonoMarshal::M_Plane *)mono_object_unbox(p_obj)); + return MARSHALLED_IN(Plane, unbox_addr<GDMonoMarshal::M_Plane>(p_obj)); + + if (vtclass == CACHED_CLASS(Callable)) + return managed_to_callable(unbox<GDMonoMarshal::M_Callable>(p_obj)); + + if (vtclass == CACHED_CLASS(SignalInfo)) + return managed_to_signal_info(unbox<GDMonoMarshal::M_SignalInfo>(p_obj)); if (mono_class_is_enum(vtclass->get_mono_ptr())) return unbox<int32_t>(p_obj); @@ -790,9 +901,15 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) return mono_array_to_PackedInt32Array((MonoArray *)p_obj); - if (array_type->eklass == REAL_T_MONOCLASS) + if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) + return mono_array_to_PackedInt64Array((MonoArray *)p_obj); + + if (array_type->eklass == CACHED_CLASS_RAW(float)) return mono_array_to_PackedFloat32Array((MonoArray *)p_obj); + if (array_type->eklass == CACHED_CLASS_RAW(double)) + return mono_array_to_PackedFloat64Array((MonoArray *)p_obj); + if (array_type->eklass == CACHED_CLASS_RAW(String)) return mono_array_to_PackedStringArray((MonoArray *)p_obj); @@ -825,6 +942,11 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type return Variant(); } + if (CACHED_CLASS(StringName) == type_class) { + StringName *ptr = unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_obj)); + return ptr ? Variant(*ptr) : Variant(); + } + if (CACHED_CLASS(NodePath) == type_class) { NodePath *ptr = unbox<NodePath *>(CACHED_FIELD(NodePath, ptr)->get_value(p_obj)); return ptr ? Variant(*ptr) : Variant(); @@ -960,9 +1082,10 @@ String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) { } MonoArray *Array_to_mono_array(const Array &p_array) { - MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_array.size()); + int length = p_array.size(); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), length); - for (int i = 0; i < p_array.size(); i++) { + for (int i = 0; i < length; i++) { MonoObject *boxed = variant_to_mono_object(p_array[i]); mono_array_setref(ret, i, boxed); } @@ -985,16 +1108,14 @@ Array mono_array_to_Array(MonoArray *p_array) { return ret; } -// TODO: Use memcpy where possible - MonoArray *PackedInt32Array_to_mono_array(const PackedInt32Array &p_array) { - const int *r = p_array.ptr(); + const int32_t *src = p_array.ptr(); + int length = p_array.size(); - MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(int32_t), p_array.size()); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(int32_t), length); - for (int i = 0; i < p_array.size(); i++) { - mono_array_set(ret, int32_t, i, r[i]); - } + int32_t *dst = (int32_t *)mono_array_addr(ret, int32_t, 0); + memcpy(dst, src, length); return ret; } @@ -1005,23 +1126,48 @@ PackedInt32Array mono_array_to_PackedInt32Array(MonoArray *p_array) { return ret; int length = mono_array_length(p_array); ret.resize(length); - int *w = ret.ptrw(); + int32_t *dst = ret.ptrw(); - for (int i = 0; i < length; i++) { - w[i] = mono_array_get(p_array, int32_t, i); - } + const int32_t *src = (const int32_t *)mono_array_addr(p_array, int32_t, 0); + memcpy(dst, src, length); + + return ret; +} + +MonoArray *PackedInt64Array_to_mono_array(const PackedInt64Array &p_array) { + const int64_t *src = p_array.ptr(); + int length = p_array.size(); + + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(int64_t), length); + + int64_t *dst = (int64_t *)mono_array_addr(ret, int64_t, 0); + memcpy(dst, src, length); + + return ret; +} + +PackedInt64Array mono_array_to_PackedInt64Array(MonoArray *p_array) { + PackedInt64Array ret; + if (!p_array) + return ret; + int length = mono_array_length(p_array); + ret.resize(length); + int64_t *dst = ret.ptrw(); + + const int64_t *src = (const int64_t *)mono_array_addr(p_array, int64_t, 0); + memcpy(dst, src, length); return ret; } MonoArray *PackedByteArray_to_mono_array(const PackedByteArray &p_array) { - const uint8_t *r = p_array.ptr(); + const uint8_t *src = p_array.ptr(); + int length = p_array.size(); - MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), p_array.size()); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), length); - for (int i = 0; i < p_array.size(); i++) { - mono_array_set(ret, uint8_t, i, r[i]); - } + uint8_t *dst = (uint8_t *)mono_array_addr(ret, uint8_t, 0); + memcpy(dst, src, length); return ret; } @@ -1032,23 +1178,22 @@ PackedByteArray mono_array_to_PackedByteArray(MonoArray *p_array) { return ret; int length = mono_array_length(p_array); ret.resize(length); - uint8_t *w = ret.ptrw(); + uint8_t *dst = ret.ptrw(); - for (int i = 0; i < length; i++) { - w[i] = mono_array_get(p_array, uint8_t, i); - } + const uint8_t *src = (const uint8_t *)mono_array_addr(p_array, uint8_t, 0); + memcpy(dst, src, length); return ret; } MonoArray *PackedFloat32Array_to_mono_array(const PackedFloat32Array &p_array) { - const real_t *r = p_array.ptr(); + const float *src = p_array.ptr(); + int length = p_array.size(); - MonoArray *ret = mono_array_new(mono_domain_get(), REAL_T_MONOCLASS, p_array.size()); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(float), length); - for (int i = 0; i < p_array.size(); i++) { - mono_array_set(ret, real_t, i, r[i]); - } + float *dst = (float *)mono_array_addr(ret, float, 0); + memcpy(dst, src, length); return ret; } @@ -1059,21 +1204,47 @@ PackedFloat32Array mono_array_to_PackedFloat32Array(MonoArray *p_array) { return ret; int length = mono_array_length(p_array); ret.resize(length); - real_t *w = ret.ptrw(); + float *dst = ret.ptrw(); - for (int i = 0; i < length; i++) { - w[i] = mono_array_get(p_array, real_t, i); - } + const float *src = (const float *)mono_array_addr(p_array, float, 0); + memcpy(dst, src, length); + + return ret; +} + +MonoArray *PackedFloat64Array_to_mono_array(const PackedFloat64Array &p_array) { + const double *src = p_array.ptr(); + int length = p_array.size(); + + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(double), length); + + double *dst = (double *)mono_array_addr(ret, double, 0); + memcpy(dst, src, length); + + return ret; +} + +PackedFloat64Array mono_array_to_PackedFloat64Array(MonoArray *p_array) { + PackedFloat64Array ret; + if (!p_array) + return ret; + int length = mono_array_length(p_array); + ret.resize(length); + double *dst = ret.ptrw(); + + const double *src = (const double *)mono_array_addr(p_array, double, 0); + memcpy(dst, src, length); return ret; } MonoArray *PackedStringArray_to_mono_array(const PackedStringArray &p_array) { const String *r = p_array.ptr(); + int length = p_array.size(); - MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), p_array.size()); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), length); - for (int i = 0; i < p_array.size(); i++) { + for (int i = 0; i < length; i++) { MonoString *boxed = mono_string_from_godot(r[i]); mono_array_setref(ret, i, boxed); } @@ -1098,13 +1269,19 @@ PackedStringArray mono_array_to_PackedStringArray(MonoArray *p_array) { } MonoArray *PackedColorArray_to_mono_array(const PackedColorArray &p_array) { - const Color *r = p_array.ptr(); + const Color *src = p_array.ptr(); + int length = p_array.size(); - MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Color), p_array.size()); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Color), length); - for (int i = 0; i < p_array.size(); i++) { - M_Color *raw = (M_Color *)mono_array_addr_with_size(ret, sizeof(M_Color), i); - *raw = MARSHALLED_OUT(Color, r[i]); + if constexpr (InteropLayout::MATCHES_Color) { + Color *dst = (Color *)mono_array_addr(ret, Color, 0); + memcpy(dst, src, length); + } else { + for (int i = 0; i < length; i++) { + M_Color *raw = (M_Color *)mono_array_addr_with_size(ret, sizeof(M_Color), i); + *raw = MARSHALLED_OUT(Color, src[i]); + } } return ret; @@ -1116,23 +1293,34 @@ PackedColorArray mono_array_to_PackedColorArray(MonoArray *p_array) { return ret; int length = mono_array_length(p_array); ret.resize(length); - Color *w = ret.ptrw(); + Color *dst = ret.ptrw(); - for (int i = 0; i < length; i++) { - w[i] = MARSHALLED_IN(Color, (M_Color *)mono_array_addr_with_size(p_array, sizeof(M_Color), i)); + if constexpr (InteropLayout::MATCHES_Color) { + const Color *src = (const Color *)mono_array_addr(p_array, Color, 0); + memcpy(dst, src, length); + } else { + for (int i = 0; i < length; i++) { + dst[i] = MARSHALLED_IN(Color, (M_Color *)mono_array_addr_with_size(p_array, sizeof(M_Color), i)); + } } return ret; } MonoArray *PackedVector2Array_to_mono_array(const PackedVector2Array &p_array) { - const Vector2 *r = p_array.ptr(); + const Vector2 *src = p_array.ptr(); + int length = p_array.size(); - MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector2), p_array.size()); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector2), length); - for (int i = 0; i < p_array.size(); i++) { - M_Vector2 *raw = (M_Vector2 *)mono_array_addr_with_size(ret, sizeof(M_Vector2), i); - *raw = MARSHALLED_OUT(Vector2, r[i]); + if constexpr (InteropLayout::MATCHES_Vector2) { + Vector2 *dst = (Vector2 *)mono_array_addr(ret, Vector2, 0); + memcpy(dst, src, length); + } else { + for (int i = 0; i < length; i++) { + M_Vector2 *raw = (M_Vector2 *)mono_array_addr_with_size(ret, sizeof(M_Vector2), i); + *raw = MARSHALLED_OUT(Vector2, src[i]); + } } return ret; @@ -1144,23 +1332,34 @@ PackedVector2Array mono_array_to_PackedVector2Array(MonoArray *p_array) { return ret; int length = mono_array_length(p_array); ret.resize(length); - Vector2 *w = ret.ptrw(); + Vector2 *dst = ret.ptrw(); - for (int i = 0; i < length; i++) { - w[i] = MARSHALLED_IN(Vector2, (M_Vector2 *)mono_array_addr_with_size(p_array, sizeof(M_Vector2), i)); + if constexpr (InteropLayout::MATCHES_Vector2) { + const Vector2 *src = (const Vector2 *)mono_array_addr(p_array, Vector2, 0); + memcpy(dst, src, length); + } else { + for (int i = 0; i < length; i++) { + dst[i] = MARSHALLED_IN(Vector2, (M_Vector2 *)mono_array_addr_with_size(p_array, sizeof(M_Vector2), i)); + } } return ret; } MonoArray *PackedVector3Array_to_mono_array(const PackedVector3Array &p_array) { - const Vector3 *r = p_array.ptr(); + const Vector3 *src = p_array.ptr(); + int length = p_array.size(); - MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector3), p_array.size()); + MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector3), length); - for (int i = 0; i < p_array.size(); i++) { - M_Vector3 *raw = (M_Vector3 *)mono_array_addr_with_size(ret, sizeof(M_Vector3), i); - *raw = MARSHALLED_OUT(Vector3, r[i]); + if constexpr (InteropLayout::MATCHES_Vector3) { + Vector3 *dst = (Vector3 *)mono_array_addr(ret, Vector3, 0); + memcpy(dst, src, length); + } else { + for (int i = 0; i < length; i++) { + M_Vector3 *raw = (M_Vector3 *)mono_array_addr_with_size(ret, sizeof(M_Vector3), i); + *raw = MARSHALLED_OUT(Vector3, src[i]); + } } return ret; @@ -1172,13 +1371,85 @@ PackedVector3Array mono_array_to_PackedVector3Array(MonoArray *p_array) { return ret; int length = mono_array_length(p_array); ret.resize(length); - Vector3 *w = ret.ptrw(); + Vector3 *dst = ret.ptrw(); - for (int i = 0; i < length; i++) { - w[i] = MARSHALLED_IN(Vector3, (M_Vector3 *)mono_array_addr_with_size(p_array, sizeof(M_Vector3), i)); + if constexpr (InteropLayout::MATCHES_Vector3) { + const Vector3 *src = (const Vector3 *)mono_array_addr(p_array, Vector3, 0); + memcpy(dst, src, length); + } else { + for (int i = 0; i < length; i++) { + dst[i] = MARSHALLED_IN(Vector3, (M_Vector3 *)mono_array_addr_with_size(p_array, sizeof(M_Vector3), i)); + } } return ret; } +Callable managed_to_callable(const M_Callable &p_managed_callable) { + if (p_managed_callable.delegate) { + // TODO: Use pooling for ManagedCallable instances. + CallableCustom *managed_callable = memnew(ManagedCallable(p_managed_callable.delegate)); + return Callable(managed_callable); + } else { + Object *target = p_managed_callable.target ? + unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_managed_callable.target)) : + NULL; + StringName *method_ptr = unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_callable.method_string_name)); + StringName method = method_ptr ? *method_ptr : StringName(); + return Callable(target, method); + } +} + +M_Callable callable_to_managed(const Callable &p_callable) { + if (p_callable.is_custom()) { + CallableCustom *custom = p_callable.get_custom(); + CallableCustom::CompareEqualFunc compare_equal_func = custom->get_compare_equal_func(); + + if (compare_equal_func == ManagedCallable::compare_equal_func_ptr) { + ManagedCallable *managed_callable = static_cast<ManagedCallable *>(custom); + return { + NULL, NULL, + managed_callable->get_delegate() + }; + } else if (compare_equal_func == SignalAwaiterCallable::compare_equal_func_ptr) { + SignalAwaiterCallable *signal_awaiter_callable = static_cast<SignalAwaiterCallable *>(custom); + return { + GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(signal_awaiter_callable->get_object())), + GDMonoUtils::create_managed_from(signal_awaiter_callable->get_signal()), + NULL + }; + } else if (compare_equal_func == EventSignalCallable::compare_equal_func_ptr) { + EventSignalCallable *event_signal_callable = static_cast<EventSignalCallable *>(custom); + return { + GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(event_signal_callable->get_object())), + GDMonoUtils::create_managed_from(event_signal_callable->get_signal()), + NULL + }; + } + + // Some other CallableCustom. We only support ManagedCallable. + return { NULL, NULL, NULL }; + } else { + MonoObject *target_managed = GDMonoUtils::unmanaged_get_managed(p_callable.get_object()); + MonoObject *method_string_name_managed = GDMonoUtils::create_managed_from(p_callable.get_method()); + return { target_managed, method_string_name_managed, NULL }; + } +} + +Signal managed_to_signal_info(const M_SignalInfo &p_managed_signal) { + Object *owner = p_managed_signal.owner ? + unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_managed_signal.owner)) : + NULL; + StringName *name_ptr = unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_signal.name_string_name)); + StringName name = name_ptr ? *name_ptr : StringName(); + return Signal(owner, name); +} + +M_SignalInfo signal_info_to_managed(const Signal &p_signal) { + Object *owner = p_signal.get_object(); + MonoObject *owner_managed = GDMonoUtils::unmanaged_get_managed(owner); + MonoObject *name_string_name_managed = GDMonoUtils::create_managed_from(p_signal.get_name()); + return { owner_managed, name_string_name_managed }; +} + } // namespace GDMonoMarshal diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 5db59522ce..7d09f46b00 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -33,6 +33,7 @@ #include "core/variant.h" +#include "../managed_callable.h" #include "gd_mono.h" #include "gd_mono_utils.h" @@ -62,7 +63,7 @@ T *unbox_addr(MonoObject *p_obj) { #define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x) #define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x) -Variant::Type managed_to_variant_type(const ManagedType &p_type); +Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_variant = NULL); bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type); bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, ManagedType &r_key_type, ManagedType &r_value_type); @@ -132,6 +133,11 @@ Array mono_array_to_Array(MonoArray *p_array); MonoArray *PackedInt32Array_to_mono_array(const PackedInt32Array &p_array); PackedInt32Array mono_array_to_PackedInt32Array(MonoArray *p_array); +// PackedInt64Array + +MonoArray *PackedInt64Array_to_mono_array(const PackedInt64Array &p_array); +PackedInt64Array mono_array_to_PackedInt64Array(MonoArray *p_array); + // PackedByteArray MonoArray *PackedByteArray_to_mono_array(const PackedByteArray &p_array); @@ -142,6 +148,11 @@ PackedByteArray mono_array_to_PackedByteArray(MonoArray *p_array); MonoArray *PackedFloat32Array_to_mono_array(const PackedFloat32Array &p_array); PackedFloat32Array mono_array_to_PackedFloat32Array(MonoArray *p_array); +// PackedFloat64Array + +MonoArray *PackedFloat64Array_to_mono_array(const PackedFloat64Array &p_array); +PackedFloat64Array mono_array_to_PackedFloat64Array(MonoArray *p_array); + // PackedStringArray MonoArray *PackedStringArray_to_mono_array(const PackedStringArray &p_array); @@ -162,11 +173,36 @@ PackedVector2Array mono_array_to_PackedVector2Array(MonoArray *p_array); MonoArray *PackedVector3Array_to_mono_array(const PackedVector3Array &p_array); PackedVector3Array mono_array_to_PackedVector3Array(MonoArray *p_array); +#pragma pack(push, 1) + +struct M_Callable { + MonoObject *target; + MonoObject *method_string_name; + MonoDelegate *delegate; +}; + +struct M_SignalInfo { + MonoObject *owner; + MonoObject *name_string_name; +}; + +#pragma pack(pop) + +// Callable +Callable managed_to_callable(const M_Callable &p_managed_callable); +M_Callable callable_to_managed(const Callable &p_callable); + +// SignalInfo +Signal managed_to_signal_info(const M_SignalInfo &p_managed_signal); +M_SignalInfo signal_info_to_managed(const Signal &p_signal); + // Structures namespace InteropLayout { enum { + MATCHES_int = (sizeof(int32_t) == sizeof(uint32_t)), + MATCHES_float = (sizeof(float) == sizeof(uint32_t)), MATCHES_double = (sizeof(double) == sizeof(uint64_t)), @@ -181,10 +217,18 @@ enum { offsetof(Vector2, x) == (sizeof(real_t) * 0) && offsetof(Vector2, y) == (sizeof(real_t) * 1)), + MATCHES_Vector2i = (MATCHES_int && (sizeof(Vector2i) == (sizeof(int32_t) * 2)) && + offsetof(Vector2i, x) == (sizeof(int32_t) * 0) && + offsetof(Vector2i, y) == (sizeof(int32_t) * 1)), + MATCHES_Rect2 = (MATCHES_Vector2 && (sizeof(Rect2) == (sizeof(Vector2) * 2)) && offsetof(Rect2, position) == (sizeof(Vector2) * 0) && offsetof(Rect2, size) == (sizeof(Vector2) * 1)), + MATCHES_Rect2i = (MATCHES_Vector2i && (sizeof(Rect2i) == (sizeof(Vector2i) * 2)) && + offsetof(Rect2i, position) == (sizeof(Vector2i) * 0) && + offsetof(Rect2i, size) == (sizeof(Vector2i) * 1)), + MATCHES_Transform2D = (MATCHES_Vector2 && (sizeof(Transform2D) == (sizeof(Vector2) * 3))), // No field offset required, it stores an array MATCHES_Vector3 = (MATCHES_real_t && (sizeof(Vector3) == (sizeof(real_t) * 3)) && @@ -192,6 +236,11 @@ enum { offsetof(Vector3, y) == (sizeof(real_t) * 1) && offsetof(Vector3, z) == (sizeof(real_t) * 2)), + MATCHES_Vector3i = (MATCHES_int && (sizeof(Vector3i) == (sizeof(int32_t) * 3)) && + offsetof(Vector3i, x) == (sizeof(int32_t) * 0) && + offsetof(Vector3i, y) == (sizeof(int32_t) * 1) && + offsetof(Vector3i, z) == (sizeof(int32_t) * 2)), + MATCHES_Basis = (MATCHES_Vector3 && (sizeof(Basis) == (sizeof(Vector3) * 3))), // No field offset required, it stores an array MATCHES_Quat = (MATCHES_real_t && (sizeof(Quat) == (sizeof(real_t) * 4)) && @@ -222,8 +271,9 @@ enum { // In the future we may force this if we want to ref return these structs #ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY /* clang-format off */ -GD_STATIC_ASSERT(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && - MATCHES_Basis && MATCHES_Quat && MATCHES_Transform && MATCHES_AABB && MATCHES_Color &&MATCHES_Plane); +static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && + MATCHES_Basis && MATCHES_Quat && MATCHES_Transform && MATCHES_AABB && MATCHES_Color && + MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i); /* clang-format on */ #endif @@ -244,6 +294,19 @@ struct M_Vector2 { } }; +struct M_Vector2i { + int32_t x, y; + + static _FORCE_INLINE_ Vector2i convert_to(const M_Vector2i &p_from) { + return Vector2i(p_from.x, p_from.y); + } + + static _FORCE_INLINE_ M_Vector2i convert_from(const Vector2i &p_from) { + M_Vector2i ret = { p_from.x, p_from.y }; + return ret; + } +}; + struct M_Rect2 { M_Vector2 position; M_Vector2 size; @@ -259,6 +322,21 @@ struct M_Rect2 { } }; +struct M_Rect2i { + M_Vector2i position; + M_Vector2i size; + + static _FORCE_INLINE_ Rect2i convert_to(const M_Rect2i &p_from) { + return Rect2i(M_Vector2i::convert_to(p_from.position), + M_Vector2i::convert_to(p_from.size)); + } + + static _FORCE_INLINE_ M_Rect2i convert_from(const Rect2i &p_from) { + M_Rect2i ret = { M_Vector2i::convert_from(p_from.position), M_Vector2i::convert_from(p_from.size) }; + return ret; + } +}; + struct M_Transform2D { M_Vector2 elements[3]; @@ -291,6 +369,19 @@ struct M_Vector3 { } }; +struct M_Vector3i { + int32_t x, y, z; + + static _FORCE_INLINE_ Vector3i convert_to(const M_Vector3i &p_from) { + return Vector3i(p_from.x, p_from.y, p_from.z); + } + + static _FORCE_INLINE_ M_Vector3i convert_from(const Vector3i &p_from) { + M_Vector3i ret = { p_from.x, p_from.y, p_from.z }; + return ret; + } +}; + struct M_Basis { M_Vector3 elements[3]; @@ -416,9 +507,12 @@ struct M_Plane { } DECL_TYPE_MARSHAL_TEMPLATES(Vector2) +DECL_TYPE_MARSHAL_TEMPLATES(Vector2i) DECL_TYPE_MARSHAL_TEMPLATES(Rect2) +DECL_TYPE_MARSHAL_TEMPLATES(Rect2i) DECL_TYPE_MARSHAL_TEMPLATES(Transform2D) DECL_TYPE_MARSHAL_TEMPLATES(Vector3) +DECL_TYPE_MARSHAL_TEMPLATES(Vector3i) DECL_TYPE_MARSHAL_TEMPLATES(Basis) DECL_TYPE_MARSHAL_TEMPLATES(Quat) DECL_TYPE_MARSHAL_TEMPLATES(Transform) diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp index 971c5ac737..e6a1ec2697 100644 --- a/modules/mono/mono_gd/gd_mono_method.cpp +++ b/modules/mono/mono_gd/gd_mono_method.cpp @@ -101,50 +101,41 @@ IMonoClassMember::Visibility GDMonoMethod::get_visibility() { } } -MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc) { - if (get_return_type().type_encoding != MONO_TYPE_VOID || get_parameters_count() > 0) { - MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), get_parameters_count()); +MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc) const { + MonoException *exc = NULL; + MonoObject *ret; + + if (params_count > 0) { + MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), params_count); for (int i = 0; i < params_count; i++) { MonoObject *boxed_param = GDMonoMarshal::variant_to_mono_object(p_params[i], param_types[i]); mono_array_setref(params, i, boxed_param); } - MonoException *exc = NULL; - MonoObject *ret = GDMonoUtils::runtime_invoke_array(mono_method, p_object, params, &exc); - - if (exc) { - ret = NULL; - if (r_exc) { - *r_exc = exc; - } else { - GDMonoUtils::set_pending_exception(exc); - } - } - - return ret; + ret = GDMonoUtils::runtime_invoke_array(mono_method, p_object, params, &exc); } else { - MonoException *exc = NULL; - GDMonoUtils::runtime_invoke(mono_method, p_object, NULL, &exc); - - if (exc) { - if (r_exc) { - *r_exc = exc; - } else { - GDMonoUtils::set_pending_exception(exc); - } - } + ret = GDMonoUtils::runtime_invoke(mono_method, p_object, NULL, &exc); + } - return NULL; + if (exc) { + ret = NULL; + if (r_exc) { + *r_exc = exc; + } else { + GDMonoUtils::set_pending_exception(exc); + } } + + return ret; } -MonoObject *GDMonoMethod::invoke(MonoObject *p_object, MonoException **r_exc) { +MonoObject *GDMonoMethod::invoke(MonoObject *p_object, MonoException **r_exc) const { ERR_FAIL_COND_V(get_parameters_count() > 0, NULL); return invoke_raw(p_object, NULL, r_exc); } -MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, MonoException **r_exc) { +MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, MonoException **r_exc) const { MonoException *exc = NULL; MonoObject *ret = GDMonoUtils::runtime_invoke(mono_method, p_object, p_params, &exc); @@ -247,7 +238,7 @@ void GDMonoMethod::get_parameter_names(Vector<StringName> &names) const { } void GDMonoMethod::get_parameter_types(Vector<ManagedType> &types) const { - for (int i = 0; i < param_types.size(); ++i) { + for (int i = 0; i < params_count; ++i) { types.push_back(param_types[i]); } } @@ -256,13 +247,22 @@ const MethodInfo &GDMonoMethod::get_method_info() { if (!method_info_fetched) { method_info.name = name; - method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type), ""); + + bool nil_is_variant = false; + method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type, &nil_is_variant), ""); + if (method_info.return_val.type == Variant::NIL && nil_is_variant) + method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; Vector<StringName> names; get_parameter_names(names); for (int i = 0; i < params_count; ++i) { - method_info.arguments.push_back(PropertyInfo(GDMonoMarshal::managed_to_variant_type(param_types[i]), names[i])); + nil_is_variant = false; + PropertyInfo arg_info = PropertyInfo(GDMonoMarshal::managed_to_variant_type(param_types[i], &nil_is_variant), names[i]); + if (arg_info.type == Variant::NIL && nil_is_variant) + arg_info.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + + method_info.arguments.push_back(arg_info); } // TODO: default arguments diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h index b47e42dec2..d4379f41fe 100644 --- a/modules/mono/mono_gd/gd_mono_method.h +++ b/modules/mono/mono_gd/gd_mono_method.h @@ -57,28 +57,28 @@ class GDMonoMethod : public IMonoClassMember { MonoMethod *mono_method; public: - virtual GDMonoClass *get_enclosing_class() const GD_FINAL; + virtual GDMonoClass *get_enclosing_class() const final; - virtual MemberType get_member_type() const GD_FINAL { return MEMBER_TYPE_METHOD; } + virtual MemberType get_member_type() const final { return MEMBER_TYPE_METHOD; } - virtual StringName get_name() const GD_FINAL { return name; } + virtual StringName get_name() const final { return name; } - virtual bool is_static() GD_FINAL; + virtual bool is_static() final; - virtual Visibility get_visibility() GD_FINAL; + virtual Visibility get_visibility() final; - virtual bool has_attribute(GDMonoClass *p_attr_class) GD_FINAL; - virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) GD_FINAL; + virtual bool has_attribute(GDMonoClass *p_attr_class) final; + virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) final; void fetch_attributes(); - _FORCE_INLINE_ MonoMethod *get_mono_ptr() { return mono_method; } + _FORCE_INLINE_ MonoMethod *get_mono_ptr() const { return mono_method; } - _FORCE_INLINE_ int get_parameters_count() { return params_count; } - _FORCE_INLINE_ ManagedType get_return_type() { return return_type; } + _FORCE_INLINE_ int get_parameters_count() const { return params_count; } + _FORCE_INLINE_ ManagedType get_return_type() const { return return_type; } - MonoObject *invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc = NULL); - MonoObject *invoke(MonoObject *p_object, MonoException **r_exc = NULL); - MonoObject *invoke_raw(MonoObject *p_object, void **p_params, MonoException **r_exc = NULL); + MonoObject *invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc = NULL) const; + MonoObject *invoke(MonoObject *p_object, MonoException **r_exc = NULL) const; + MonoObject *invoke_raw(MonoObject *p_object, void **p_params, MonoException **r_exc = NULL) const; String get_full_name(bool p_signature = false) const; String get_full_name_no_class() const; diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h index 692037f76a..2aec64f565 100644 --- a/modules/mono/mono_gd/gd_mono_property.h +++ b/modules/mono/mono_gd/gd_mono_property.h @@ -47,17 +47,17 @@ class GDMonoProperty : public IMonoClassMember { MonoCustomAttrInfo *attributes; public: - virtual GDMonoClass *get_enclosing_class() const GD_FINAL { return owner; } + virtual GDMonoClass *get_enclosing_class() const final { return owner; } - virtual MemberType get_member_type() const GD_FINAL { return MEMBER_TYPE_PROPERTY; } + virtual MemberType get_member_type() const final { return MEMBER_TYPE_PROPERTY; } - virtual StringName get_name() const GD_FINAL { return name; } + virtual StringName get_name() const final { return name; } - virtual bool is_static() GD_FINAL; - virtual Visibility get_visibility() GD_FINAL; + virtual bool is_static() final; + virtual Visibility get_visibility() final; - virtual bool has_attribute(GDMonoClass *p_attr_class) GD_FINAL; - virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) GD_FINAL; + virtual bool has_attribute(GDMonoClass *p_attr_class) final; + virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) final; void fetch_attributes(); bool has_getter(); diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index bc290f3a7f..cdb26ae61b 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -86,10 +86,9 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { } } - Ref<MonoGCHandle> &gchandle = script_binding.gchandle; - ERR_FAIL_COND_V(gchandle.is_null(), NULL); + MonoGCHandleData &gchandle = script_binding.gchandle; - MonoObject *target = gchandle->get_target(); + MonoObject *target = gchandle.get_target(); if (target) return target; @@ -106,7 +105,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(script_binding.wrapper_class, script_binding.type_name, unmanaged); ERR_FAIL_NULL_V(mono_object, NULL); - gchandle->set_handle(MonoGCHandle::new_strong_handle(mono_object), MonoGCHandle::STRONG_HANDLE); + gchandle = MonoGCHandleData::new_strong_handle(mono_object); // Tie managed to unmanaged Reference *ref = Object::cast_to<Reference>(unmanaged); @@ -156,12 +155,35 @@ bool is_thread_attached() { return mono_domain_get() != NULL; } +uint32_t new_strong_gchandle(MonoObject *p_object) { + return mono_gchandle_new(p_object, /* pinned: */ false); +} + +uint32_t new_strong_gchandle_pinned(MonoObject *p_object) { + return mono_gchandle_new(p_object, /* pinned: */ true); +} + +uint32_t new_weak_gchandle(MonoObject *p_object) { + return mono_gchandle_new_weakref(p_object, /* track_resurrection: */ false); +} + +void free_gchandle(uint32_t p_gchandle) { + mono_gchandle_free(p_gchandle); +} + void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) { GDMonoMethod *ctor = p_class->get_method(".ctor", 0); ERR_FAIL_NULL(ctor); ctor->invoke_raw(p_this_obj, NULL, r_exc); } +bool mono_delegate_equal(MonoDelegate *p_a, MonoDelegate *p_b) { + MonoException *exc = NULL; + MonoBoolean res = CACHED_METHOD_THUNK(Delegate, Equals).invoke((MonoObject *)p_a, (MonoObject *)p_b, &exc); + UNHANDLED_EXCEPTION(exc); + return (bool)res; +} + GDMonoClass *get_object_class(MonoObject *p_object) { return GDMono::get_singleton()->get_class(mono_object_get_class(p_object)); } @@ -220,6 +242,18 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa return mono_object; } +MonoObject *create_managed_from(const StringName &p_from) { + MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(StringName)); + ERR_FAIL_NULL_V(mono_object, NULL); + + // Construct + GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(StringName)); + + CACHED_FIELD(StringName, ptr)->set_value_raw(mono_object, memnew(StringName(p_from))); + + return mono_object; +} + MonoObject *create_managed_from(const NodePath &p_from) { MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(NodePath)); ERR_FAIL_NULL_V(mono_object, NULL); @@ -362,7 +396,11 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { return; } - _TLS_RECURSION_GUARD_; + static thread_local bool _recursion_flag_ = false; + if (_recursion_flag_) + return; + _recursion_flag_ = true; + SCOPE_EXIT { _recursion_flag_ = false; }; ScriptLanguage::StackInfo separator; separator.file = String(); @@ -439,8 +477,7 @@ void set_pending_exception(MonoException *p_exc) { #endif } -_THREAD_LOCAL_(int) -current_invoke_count = 0; +thread_local int current_invoke_count = 0; MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc) { GD_MONO_BEGIN_RUNTIME_INVOKE; @@ -644,6 +681,10 @@ ScopeThreadAttach::~ScopeThreadAttach() { } } -// namespace Marshal +StringName get_native_godot_class_name(GDMonoClass *p_class) { + MonoObject *native_name_obj = p_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL); + StringName *ptr = GDMonoMarshal::unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(native_name_obj)); + return ptr ? *ptr : StringName(); +} } // namespace GDMonoUtils diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index db9f99bfdc..fd02907d87 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -35,7 +35,6 @@ #include "../mono_gc_handle.h" #include "../utils/macros.h" -#include "../utils/thread_local.h" #include "gd_mono_header.h" #include "core/object.h" @@ -93,14 +92,22 @@ _FORCE_INLINE_ bool is_main_thread() { return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current(); } +uint32_t new_strong_gchandle(MonoObject *p_object); +uint32_t new_strong_gchandle_pinned(MonoObject *p_object); +uint32_t new_weak_gchandle(MonoObject *p_object); +void free_gchandle(uint32_t p_gchandle); + void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc = NULL); +bool mono_delegate_equal(MonoDelegate *p_a, MonoDelegate *p_b); + GDMonoClass *get_object_class(MonoObject *p_object); GDMonoClass *type_get_proxy_class(const StringName &p_type); GDMonoClass *get_class_native_base(GDMonoClass *p_class); MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object); +MonoObject *create_managed_from(const StringName &p_from); MonoObject *create_managed_from(const NodePath &p_from); MonoObject *create_managed_from(const RID &p_from); MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class); @@ -123,7 +130,7 @@ void print_unhandled_exception(MonoException *p_exc); */ void set_pending_exception(MonoException *p_exc); -extern _THREAD_LOCAL_(int) current_invoke_count; +extern thread_local int current_invoke_count; _FORCE_INLINE_ int get_runtime_invoke_count() { return current_invoke_count; @@ -152,9 +159,11 @@ private: MonoThread *mono_thread; }; +StringName get_native_godot_class_name(GDMonoClass *p_class); + } // namespace GDMonoUtils -#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL))) +#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoUtils::get_native_godot_class_name(m_class)) #define GD_MONO_BEGIN_RUNTIME_INVOKE \ int &_runtime_invoke_count_ref = GDMonoUtils::get_runtime_invoke_count_ref(); \ |