summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs4
-rw-r--r--modules/mono/glue/Managed/Files/MarshalUtils.cs40
-rw-r--r--modules/mono/glue/Managed/IgnoredFiles/Node.cs5
-rw-r--r--modules/mono/glue/collections_glue.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp24
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp45
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h12
7 files changed, 95 insertions, 39 deletions
diff --git a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
index 366d89b1c2..5023725f17 100644
--- a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
+++ b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
@@ -24,12 +24,12 @@ namespace Godot
public T GetOwner<T>() where T : class
{
- return (T)(object)GetOwner();
+ return (T)(object)Owner;
}
public T GetOwnerOrNull<T>() where T : class
{
- return GetOwner() as T;
+ return Owner as T;
}
public T GetParent<T>() where T : class
diff --git a/modules/mono/glue/Managed/Files/MarshalUtils.cs b/modules/mono/glue/Managed/Files/MarshalUtils.cs
index 730a1e1585..a1d63a62ef 100644
--- a/modules/mono/glue/Managed/Files/MarshalUtils.cs
+++ b/modules/mono/glue/Managed/Files/MarshalUtils.cs
@@ -23,7 +23,7 @@ namespace Godot
/// <summary>
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
- /// is <see cref="Godot.Collections.Dictionary{T}"/>; otherwise returns <see langword="false"/>.
+ /// is <see cref="Godot.Collections.Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
/// </summary>
/// <exception cref="System.InvalidOperationException">
/// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
@@ -45,6 +45,44 @@ namespace Godot
valueType = genericArgs[1];
}
+ static bool GenericIEnumerableIsAssignableFromType(Type type)
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ return true;
+
+ foreach (var interfaceType in type.GetInterfaces())
+ {
+ if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ return true;
+ }
+
+ Type baseType = type.BaseType;
+
+ if (baseType == null)
+ return false;
+
+ return GenericIEnumerableIsAssignableFromType(baseType);
+ }
+
+ static bool GenericIDictionaryIsAssignableFromType(Type type)
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+ return true;
+
+ foreach (var interfaceType in type.GetInterfaces())
+ {
+ if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+ return true;
+ }
+
+ Type baseType = type.BaseType;
+
+ if (baseType == null)
+ return false;
+
+ return GenericIDictionaryIsAssignableFromType(baseType);
+ }
+
static bool GenericIEnumerableIsAssignableFromType(Type type, out Type elementType)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
diff --git a/modules/mono/glue/Managed/IgnoredFiles/Node.cs b/modules/mono/glue/Managed/IgnoredFiles/Node.cs
index 99ba0f827a..cff61b1e0b 100644
--- a/modules/mono/glue/Managed/IgnoredFiles/Node.cs
+++ b/modules/mono/glue/Managed/IgnoredFiles/Node.cs
@@ -15,9 +15,10 @@ namespace Godot
throw new NotImplementedException();
}
- public Node GetOwner()
+ public Node Owner
{
- throw new NotImplementedException();
+ get => throw new NotImplementedException();
+ set => throw new NotImplementedException();
}
public Node GetParent()
diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp
index 4aef5684fd..47239f1260 100644
--- a/modules/mono/glue/collections_glue.cpp
+++ b/modules/mono/glue/collections_glue.cpp
@@ -162,7 +162,7 @@ MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
#ifdef DEBUG_ENABLED
CRASH_COND(!exc);
#endif
- GDMonoUtils::runtime_object_init(exc);
+ GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
GDMonoUtils::set_pending_exception((MonoException *)exc);
return NULL;
}
@@ -176,7 +176,7 @@ MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject
#ifdef DEBUG_ENABLED
CRASH_COND(!exc);
#endif
- GDMonoUtils::runtime_object_init(exc);
+ GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
GDMonoUtils::set_pending_exception((MonoException *)exc);
return NULL;
}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 461dcf3ec0..c462b8f71d 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -161,8 +161,7 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, type_class->get_mono_type());
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) {
+ if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) {
return Variant::DICTIONARY;
}
@@ -170,8 +169,7 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
return Variant::DICTIONARY;
}
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) {
+ if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) {
return Variant::ARRAY;
}
@@ -193,16 +191,14 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
// The order in which we check the following interfaces is very important (dictionaries and generics first)
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype))
+ if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype))
return Variant::DICTIONARY;
if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
return Variant::DICTIONARY;
}
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype))
+ if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype))
return Variant::ARRAY;
if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
@@ -850,8 +846,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, type_class->get_mono_type());
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) {
+ if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) {
return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj);
}
@@ -859,8 +854,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj);
}
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) {
+ if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) {
return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
}
@@ -888,8 +882,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
// The order in which we check the following interfaces is very important (dictionaries and generics first)
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) {
+ if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) {
return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj);
}
@@ -897,8 +890,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj);
}
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) {
+ if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) {
return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
}
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 5236e43c90..413c8cba85 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -161,6 +161,8 @@ void MonoCache::clear_members() {
methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType = NULL;
methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType = NULL;
+ methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info = NULL;
+ methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info = NULL;
methodthunk_MarshalUtils_MakeGenericArrayType = NULL;
methodthunk_MarshalUtils_MakeGenericDictionaryType = NULL;
@@ -282,8 +284,10 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, (GenericIEnumerableIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 2));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, (GenericIDictionaryIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, (GenericIEnumerableIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, (GenericIDictionaryIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 2));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, (MakeGenericArrayType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericArrayType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, (MakeGenericDictionaryType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericDictionaryType", 2));
@@ -300,7 +304,7 @@ void update_godot_api_cache() {
// TODO Move to CSharpLanguage::init() and do handle disposal
MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
- GDMonoUtils::runtime_object_init(task_scheduler);
+ GDMonoUtils::runtime_object_init(task_scheduler, GODOT_API_CLASS(GodotTaskScheduler));
mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
mono_cache.godot_api_cache_updated = true;
@@ -401,11 +405,10 @@ MonoThread *get_current_thread() {
return mono_thread_current();
}
-void runtime_object_init(MonoObject *p_this_obj) {
- GD_MONO_BEGIN_RUNTIME_INVOKE;
- // FIXME: Do not use mono_runtime_object_init, it aborts if an exception is thrown
- mono_runtime_object_init(p_this_obj);
- GD_MONO_END_RUNTIME_INVOKE;
+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);
}
GDMonoClass *get_object_class(MonoObject *p_object) {
@@ -467,7 +470,7 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa
CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
// Construct
- GDMonoUtils::runtime_object_init(mono_object);
+ GDMonoUtils::runtime_object_init(mono_object, p_class);
return mono_object;
}
@@ -477,7 +480,7 @@ MonoObject *create_managed_from(const NodePath &p_from) {
ERR_FAIL_NULL_V(mono_object, NULL);
// Construct
- GDMonoUtils::runtime_object_init(mono_object);
+ GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(NodePath));
CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
@@ -489,7 +492,7 @@ MonoObject *create_managed_from(const RID &p_from) {
ERR_FAIL_NULL_V(mono_object, NULL);
// Construct
- GDMonoUtils::runtime_object_init(mono_object);
+ GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(RID));
CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
@@ -788,16 +791,32 @@ void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoRefl
UNLIKELY_UNHANDLED_EXCEPTION(exc);
}
-MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) {
+MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) {
GenericIEnumerableIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType);
MonoException *exc = NULL;
+ MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+ return res;
+}
+
+MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) {
+ GenericIDictionaryIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType);
+ MonoException *exc = NULL;
+ MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+ return res;
+}
+
+MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) {
+ GenericIEnumerableIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info);
+ MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_elem_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return res;
}
MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
- GenericIDictionaryIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType);
+ GenericIDictionaryIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info);
MonoException *exc = NULL;
MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_key_reftype, r_value_reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 081a8a9813..ee239be959 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -64,8 +64,10 @@ typedef MonoBoolean (*TypeIsGenericDictionary)(MonoReflectionType *, MonoExcepti
typedef void (*ArrayGetElementType)(MonoReflectionType *, MonoReflectionType **, MonoException **);
typedef void (*DictionaryGetKeyValueTypes)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **);
-typedef MonoBoolean (*GenericIEnumerableIsAssignableFromType)(MonoReflectionType *, MonoReflectionType **, MonoException **);
-typedef MonoBoolean (*GenericIDictionaryIsAssignableFromType)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **);
+typedef MonoBoolean (*GenericIEnumerableIsAssignableFromType)(MonoReflectionType *, MonoException **);
+typedef MonoBoolean (*GenericIDictionaryIsAssignableFromType)(MonoReflectionType *, MonoException **);
+typedef MonoBoolean (*GenericIEnumerableIsAssignableFromType_with_info)(MonoReflectionType *, MonoReflectionType **, MonoException **);
+typedef MonoBoolean (*GenericIDictionaryIsAssignableFromType_with_info)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **);
typedef MonoReflectionType *(*MakeGenericArrayType)(MonoReflectionType *, MonoException **);
typedef MonoReflectionType *(*MakeGenericDictionaryType)(MonoReflectionType *, MonoReflectionType *, MonoException **);
@@ -82,6 +84,8 @@ MonoBoolean type_is_generic_dictionary(MonoReflectionType *p_reftype);
void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype);
void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype);
+MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype);
+MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype);
MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype);
MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype);
@@ -197,6 +201,8 @@ struct MonoCache {
GenericIEnumerableIsAssignableFromType methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType;
GenericIDictionaryIsAssignableFromType methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType;
+ GenericIEnumerableIsAssignableFromType_with_info methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info;
+ GenericIDictionaryIsAssignableFromType_with_info methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info;
MakeGenericArrayType methodthunk_MarshalUtils_MakeGenericArrayType;
MakeGenericDictionaryType methodthunk_MarshalUtils_MakeGenericDictionaryType;
@@ -249,7 +255,7 @@ _FORCE_INLINE_ bool is_main_thread() {
return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current();
}
-void runtime_object_init(MonoObject *p_this_obj);
+void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc = NULL);
GDMonoClass *get_object_class(MonoObject *p_object);
GDMonoClass *type_get_proxy_class(const StringName &p_type);