Browse Source

C#: Fix property set call boxing value when unboxed was expected

Ignacio Roldán Etcheverry 3 năm trước cách đây
mục cha
commit
cad05f012d

+ 1 - 1
modules/mono/csharp_script.cpp

@@ -1660,7 +1660,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
 		GDMonoProperty *property = top->get_property(p_name);
 
 		if (property) {
-			property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object(p_value, property->get_type()));
+			property->set_value_from_variant(mono_object, p_value);
 			return true;
 		}
 

+ 14 - 16
modules/mono/mono_gd/gd_mono_property.cpp

@@ -65,6 +65,8 @@ GDMonoProperty::GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_own
 		type.type_class = GDMono::get_singleton()->get_class(param_type_class);
 	}
 
+	param_buffer_size = GDMonoMarshal::variant_get_managed_unboxed_size(type);
+
 	attrs_fetched = false;
 	attributes = nullptr;
 }
@@ -147,24 +149,20 @@ bool GDMonoProperty::has_setter() {
 	return mono_property_get_set_method(mono_property) != nullptr;
 }
 
-void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) {
-	MonoMethod *prop_method = mono_property_get_set_method(mono_property);
-	void *params[1] = { p_value };
-	MonoException *exc = nullptr;
-	GDMonoUtils::runtime_invoke(prop_method, p_object, params, &exc);
-	if (exc) {
-		if (r_exc) {
-			*r_exc = exc;
-		} else {
-			GDMonoUtils::set_pending_exception(exc);
-		}
-	}
-}
+void GDMonoProperty::set_value_from_variant(MonoObject *p_object, const Variant &p_value, MonoException **r_exc) {
+	uint8_t *buffer = (uint8_t *)alloca(param_buffer_size);
+	unsigned int offset = 0;
 
-void GDMonoProperty::set_value(MonoObject *p_object, void **p_params, MonoException **r_exc) {
-	MonoException *exc = nullptr;
-	GDMonoUtils::property_set_value(mono_property, p_object, p_params, &exc);
+	void *params[1] = {
+		GDMonoMarshal::variant_to_managed_unboxed(p_value, type, buffer, offset)
+	};
+
+#ifdef DEBUG_ENABLED
+	CRASH_COND(offset != param_buffer_size);
+#endif
 
+	MonoException *exc = nullptr;
+	GDMonoUtils::property_set_value(mono_property, p_object, params, &exc);
 	if (exc) {
 		if (r_exc) {
 			*r_exc = exc;

+ 3 - 2
modules/mono/mono_gd/gd_mono_property.h

@@ -45,6 +45,8 @@ class GDMonoProperty : public IMonoClassMember {
 	bool attrs_fetched;
 	MonoCustomAttrInfo *attributes;
 
+	unsigned int param_buffer_size;
+
 public:
 	virtual GDMonoClass *get_enclosing_class() const final { return owner; }
 
@@ -64,8 +66,7 @@ public:
 
 	_FORCE_INLINE_ ManagedType get_type() const { return type; }
 
-	void set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc = nullptr);
-	void set_value(MonoObject *p_object, void **p_params, MonoException **r_exc = nullptr);
+	void set_value_from_variant(MonoObject *p_object, const Variant &p_value, MonoException **r_exc = nullptr);
 	MonoObject *get_value(MonoObject *p_object, MonoException **r_exc = nullptr);
 
 	bool get_bool_value(MonoObject *p_object);