summaryrefslogtreecommitdiff
path: root/modules/mono/mono_gd/gd_mono_marshal.cpp
diff options
context:
space:
mode:
authorIgnacio Etcheverry <ignalfonsore@gmail.com>2020-01-02 13:54:16 +0100
committerIgnacio Etcheverry <ignalfonsore@gmail.com>2020-01-02 13:54:20 +0100
commit844a8d215b1fa768440d5233c532f6e71c54fc14 (patch)
treeeae988c1ae1d36466f5ceca09e0eee57e62bb8d8 /modules/mono/mono_gd/gd_mono_marshal.cpp
parentea75ea50d2b0f76c44e02e6fd8a558788cc375f6 (diff)
Mono/C#: Make 'GD.Print' and its variants fallback to 'ToString()'
Up until now, 'GD.Print' would convert parameters first to Variant and only then to String. This meant parameters that cannot be converted to Variant would be printed as "Null". This commit makes 'GD.Print' fallback to 'System.Object.ToString()' if the parameter could not be converted to Variant. The same applies to all 'GD.Print' variants: 'GD.PrintS', 'GD.PrintT', 'GD.PrintErr' and 'GD.PrintRaw'.
Diffstat (limited to 'modules/mono/mono_gd/gd_mono_marshal.cpp')
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp84
1 files changed, 66 insertions, 18 deletions
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 24fcd27bbb..b81c20348d 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -700,15 +700,11 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
p_type.type_class->get_name() + "' Encoding: " + itos(p_type.type_encoding) + ".");
}
-Variant mono_object_to_variant(MonoObject *p_obj) {
- if (!p_obj)
- return Variant();
+Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type, bool p_fail_with_err = true) {
- ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj));
-
- ERR_FAIL_COND_V(!type.type_class, Variant());
+ ERR_FAIL_COND_V(!p_type.type_class, Variant());
- switch (type.type_encoding) {
+ switch (p_type.type_encoding) {
case MONO_TYPE_BOOLEAN:
return (bool)unbox<MonoBoolean>(p_obj);
@@ -745,7 +741,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
} break;
case MONO_TYPE_VALUETYPE: {
- GDMonoClass *vtclass = type.type_class;
+ GDMonoClass *vtclass = p_type.type_class;
if (vtclass == CACHED_CLASS(Vector2))
return MARSHALLED_IN(Vector2, (GDMonoMarshal::M_Vector2 *)mono_object_unbox(p_obj));
@@ -783,7 +779,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY: {
- MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
+ MonoArrayType *array_type = mono_type_get_array_type(p_type.type_class->get_mono_type());
if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
return mono_array_to_Array((MonoArray *)p_obj);
@@ -809,11 +805,15 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
if (array_type->eklass == CACHED_CLASS_RAW(Color))
return mono_array_to_PoolColorArray((MonoArray *)p_obj);
- ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant.");
+ if (p_fail_with_err) {
+ ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant.");
+ } else {
+ return Variant();
+ }
} break;
case MONO_TYPE_CLASS: {
- GDMonoClass *type_class = type.type_class;
+ GDMonoClass *type_class = p_type.type_class;
// GodotObject
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
@@ -871,18 +871,18 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
} break;
case MONO_TYPE_GENERICINST: {
- MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type.type_class->get_mono_type());
+ MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
MonoException *exc = NULL;
- MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
+ MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
UNHANDLED_EXCEPTION(exc);
return *unbox<Dictionary *>(ret);
}
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
MonoException *exc = NULL;
- MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
+ MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
UNHANDLED_EXCEPTION(exc);
return *unbox<Array *>(ret);
}
@@ -893,7 +893,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj);
}
- if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj);
}
@@ -901,14 +901,62 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
}
- if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
}
} break;
}
- ERR_FAIL_V_MSG(Variant(), "Attempted to convert an unmarshallable managed type to Variant. Name: '" +
- type.type_class->get_name() + "' Encoding: " + itos(type.type_encoding) + ".");
+ if (p_fail_with_err) {
+ ERR_FAIL_V_MSG(Variant(), "Attempted to convert an unmarshallable managed type to Variant. Name: '" +
+ p_type.type_class->get_name() + "' Encoding: " + itos(p_type.type_encoding) + ".");
+ } else {
+ return Variant();
+ }
+}
+
+Variant mono_object_to_variant(MonoObject *p_obj) {
+ if (!p_obj)
+ return Variant();
+
+ ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj));
+
+ return mono_object_to_variant_impl(p_obj, type);
+}
+
+Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
+ if (!p_obj)
+ return Variant();
+
+ return mono_object_to_variant_impl(p_obj, p_type);
+}
+
+Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_type) {
+ if (!p_obj)
+ return Variant();
+
+ return mono_object_to_variant_impl(p_obj, p_type, /* fail_with_err: */ false);
+}
+
+String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) {
+ ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj));
+ Variant var = GDMonoMarshal::mono_object_to_variant_no_err(p_obj, type);
+
+ if (var.get_type() == Variant::NIL && p_obj != NULL) {
+ // Cannot convert MonoObject* to Variant; fallback to 'ToString()'.
+ MonoException *exc = NULL;
+ MonoString *mono_str = GDMonoUtils::object_to_string(p_obj, &exc);
+
+ if (exc) {
+ if (r_exc)
+ *r_exc = exc;
+ return String();
+ }
+
+ return GDMonoMarshal::mono_string_to_godot(mono_str);
+ } else {
+ return var.operator String();
+ }
}
MonoArray *Array_to_mono_array(const Array &p_array) {