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'.
This commit is contained in:
parent
ea75ea50d2
commit
844a8d215b
@ -71,48 +71,114 @@ MonoObject *godot_icall_GD_instance_from_id(uint64_t p_instance_id) {
|
||||
}
|
||||
|
||||
void godot_icall_GD_print(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++)
|
||||
str += what[i].operator String();
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printerr(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++)
|
||||
str += what[i].operator String();
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_error(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printraw(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++)
|
||||
str += what[i].operator String();
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
OS::get_singleton()->print("%s", str.utf8().get_data());
|
||||
}
|
||||
|
||||
void godot_icall_GD_prints(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++) {
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i)
|
||||
str += " ";
|
||||
str += what[i].operator String();
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printt(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++) {
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i)
|
||||
str += "\t";
|
||||
str += what[i].operator String();
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
|
@ -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(!p_type.type_class, Variant());
|
||||
|
||||
ERR_FAIL_COND_V(!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) {
|
||||
|
@ -115,6 +115,12 @@ _FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var, const Ma
|
||||
}
|
||||
|
||||
Variant mono_object_to_variant(MonoObject *p_obj);
|
||||
Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type);
|
||||
Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_type);
|
||||
|
||||
/// Tries to convert the MonoObject* to Variant and then convert the Variant to String.
|
||||
/// If the MonoObject* cannot be converted to Variant, then 'ToString()' is called instead.
|
||||
String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc);
|
||||
|
||||
// Array
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user