Don't box params on Native->C# calls with Variant params
Godot uses Variant parameters for calls to script methods. Up until now we were boxing such parameters when marshalling them for invokation, even if they were value types. Now Godot allocates the marshalled parameters on the stack, reducing the GC allocations resulted from boxing.
This commit is contained in:
parent
a05aefb74b
commit
b775573a21
12 changed files with 712 additions and 649 deletions
|
@ -2479,7 +2479,7 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Ve
|
|||
|
||||
if (mono_type_get_type(raw_type) == MONO_TYPE_CLASS) {
|
||||
// Arguments are accessibles as arguments of .Invoke method
|
||||
GDMonoMethod *invoke = p_delegate->get_method("Invoke", -1);
|
||||
GDMonoMethod *invoke = p_delegate->get_method(mono_get_delegate_invoke(p_delegate->get_mono_ptr()));
|
||||
|
||||
Vector<StringName> names;
|
||||
Vector<ManagedType> types;
|
||||
|
|
|
@ -278,7 +278,7 @@ bool GDMonoClass::has_public_parameterless_ctor() {
|
|||
return ctor && ctor->get_visibility() == IMonoClassMember::PUBLIC;
|
||||
}
|
||||
|
||||
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) {
|
||||
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, uint16_t p_params_count) {
|
||||
MethodKey key = MethodKey(p_name, p_params_count);
|
||||
|
||||
GDMonoMethod **match = methods.getptr(key);
|
||||
|
@ -316,7 +316,7 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName
|
|||
return get_method(p_raw_method, p_name, params_count);
|
||||
}
|
||||
|
||||
GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count) {
|
||||
GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name, uint16_t p_params_count) {
|
||||
ERR_FAIL_NULL_V(p_raw_method, NULL);
|
||||
|
||||
MethodKey key = MethodKey(p_name, p_params_count);
|
||||
|
|
|
@ -59,13 +59,13 @@ class GDMonoClass {
|
|||
|
||||
MethodKey() {}
|
||||
|
||||
MethodKey(const StringName &p_name, int p_params_count) {
|
||||
MethodKey(const StringName &p_name, uint16_t p_params_count) {
|
||||
name = p_name;
|
||||
params_count = p_params_count;
|
||||
}
|
||||
|
||||
StringName name;
|
||||
int params_count;
|
||||
uint16_t params_count;
|
||||
};
|
||||
|
||||
StringName namespace_name;
|
||||
|
@ -139,10 +139,10 @@ public:
|
|||
bool implements_interface(GDMonoClass *p_interface);
|
||||
bool has_public_parameterless_ctor();
|
||||
|
||||
GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0);
|
||||
GDMonoMethod *get_method(const StringName &p_name, uint16_t p_params_count = 0);
|
||||
GDMonoMethod *get_method(MonoMethod *p_raw_method);
|
||||
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name);
|
||||
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count);
|
||||
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, uint16_t p_params_count);
|
||||
GDMonoMethod *get_method_with_desc(const String &p_description, bool p_include_namespace);
|
||||
|
||||
GDMonoField *get_field(const StringName &p_name);
|
||||
|
|
|
@ -42,29 +42,15 @@ void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) {
|
|||
}
|
||||
|
||||
void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_value) {
|
||||
#define SET_FROM_STRUCT(m_type) \
|
||||
{ \
|
||||
GDMonoMarshal::M_##m_type from = MARSHALLED_OUT(m_type, p_value.operator ::m_type()); \
|
||||
mono_field_set_value(p_object, mono_field, &from); \
|
||||
}
|
||||
|
||||
#define SET_FROM_ARRAY(m_type) \
|
||||
{ \
|
||||
MonoArray *managed = GDMonoMarshal::m_type##_to_mono_array(p_value.operator ::m_type()); \
|
||||
mono_field_set_value(p_object, mono_field, managed); \
|
||||
}
|
||||
|
||||
switch (type.type_encoding) {
|
||||
case MONO_TYPE_BOOLEAN: {
|
||||
MonoBoolean val = p_value.operator bool();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_CHAR: {
|
||||
int16_t val = p_value.operator unsigned short();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_I1: {
|
||||
int8_t val = p_value.operator signed char();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
|
@ -81,7 +67,6 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
|
|||
int64_t val = p_value.operator int64_t();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_U1: {
|
||||
uint8_t val = p_value.operator unsigned char();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
|
@ -98,78 +83,74 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
|
|||
uint64_t val = p_value.operator uint64_t();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_R4: {
|
||||
float val = p_value.operator float();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_R8: {
|
||||
double val = p_value.operator double();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_STRING: {
|
||||
if (p_value.get_type() == Variant::NIL) {
|
||||
// Otherwise, Variant -> String would return the string "Null"
|
||||
MonoString *mono_string = NULL;
|
||||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
} else {
|
||||
MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
|
||||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
}
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_VALUETYPE: {
|
||||
GDMonoClass *tclass = type.type_class;
|
||||
|
||||
if (tclass == CACHED_CLASS(Vector2)) {
|
||||
SET_FROM_STRUCT(Vector2);
|
||||
GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_value.operator ::Vector2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Rect2)) {
|
||||
SET_FROM_STRUCT(Rect2);
|
||||
GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_value.operator ::Rect2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Transform2D)) {
|
||||
SET_FROM_STRUCT(Transform2D);
|
||||
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Vector3)) {
|
||||
SET_FROM_STRUCT(Vector3);
|
||||
GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_value.operator ::Vector3());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Basis)) {
|
||||
SET_FROM_STRUCT(Basis);
|
||||
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Quat)) {
|
||||
SET_FROM_STRUCT(Quat);
|
||||
GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Transform)) {
|
||||
SET_FROM_STRUCT(Transform);
|
||||
GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(AABB)) {
|
||||
SET_FROM_STRUCT(AABB);
|
||||
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Color)) {
|
||||
SET_FROM_STRUCT(Color);
|
||||
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Plane)) {
|
||||
SET_FROM_STRUCT(Plane);
|
||||
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -236,112 +217,35 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
|
|||
|
||||
ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + tclass->get_name() + "'.");
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_STRING: {
|
||||
if (p_value.get_type() == Variant::NIL) {
|
||||
// Otherwise, Variant -> String would return the string "Null"
|
||||
MonoString *mono_string = NULL;
|
||||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
} else {
|
||||
MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
|
||||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
}
|
||||
} break;
|
||||
case MONO_TYPE_ARRAY:
|
||||
case MONO_TYPE_SZARRAY: {
|
||||
MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) {
|
||||
SET_FROM_ARRAY(Array);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) {
|
||||
SET_FROM_ARRAY(PoolByteArray);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) {
|
||||
SET_FROM_ARRAY(PoolIntArray);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == REAL_T_MONOCLASS) {
|
||||
SET_FROM_ARRAY(PoolRealArray);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(String)) {
|
||||
SET_FROM_ARRAY(PoolStringArray);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) {
|
||||
SET_FROM_ARRAY(PoolVector2Array);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) {
|
||||
SET_FROM_ARRAY(PoolVector3Array);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(Color)) {
|
||||
SET_FROM_ARRAY(PoolColorArray);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(NodePath)) {
|
||||
SET_FROM_ARRAY(Array);
|
||||
break;
|
||||
}
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(RID)) {
|
||||
SET_FROM_ARRAY(Array);
|
||||
break;
|
||||
}
|
||||
|
||||
GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
|
||||
if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) {
|
||||
MonoArray *managed = GDMonoMarshal::Array_to_mono_array(p_value.operator ::Array(), array_type_class);
|
||||
MonoArray *managed = GDMonoMarshal::variant_to_mono_array(p_value, type.type_class);
|
||||
if (likely(managed != nullptr)) {
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type.");
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_CLASS: {
|
||||
GDMonoClass *type_class = type.type_class;
|
||||
|
||||
// GodotObject
|
||||
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
|
||||
MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
|
||||
MonoObject *managed = GDMonoMarshal::variant_to_mono_object_of_class(p_value, type.type_class);
|
||||
if (likely(managed != nullptr)) {
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
}
|
||||
} break;
|
||||
case MONO_TYPE_GENERICINST: {
|
||||
MonoObject *managed = GDMonoMarshal::variant_to_mono_object_of_genericinst(p_value, type.type_class);
|
||||
if (likely(managed != nullptr)) {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
if (CACHED_CLASS(RID) == type_class) {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator RID());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// Godot.Collections.Dictionary or IDictionary
|
||||
if (CACHED_CLASS(Dictionary) == type_class || type_class == CACHED_CLASS(System_Collections_IDictionary)) {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// Godot.Collections.Array or ICollection or IEnumerable
|
||||
if (CACHED_CLASS(Array) == type_class ||
|
||||
type_class == CACHED_CLASS(System_Collections_ICollection) ||
|
||||
type_class == CACHED_CLASS(System_Collections_IEnumerable)) {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + type_class->get_name() + "'.");
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_OBJECT: {
|
||||
// Variant
|
||||
switch (p_value.get_type()) {
|
||||
|
@ -367,34 +271,44 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
|
|||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
} break;
|
||||
case Variant::VECTOR2: {
|
||||
SET_FROM_STRUCT(Vector2);
|
||||
GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_value.operator ::Vector2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::RECT2: {
|
||||
SET_FROM_STRUCT(Rect2);
|
||||
GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_value.operator ::Rect2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::VECTOR3: {
|
||||
SET_FROM_STRUCT(Vector3);
|
||||
GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_value.operator ::Vector3());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::TRANSFORM2D: {
|
||||
SET_FROM_STRUCT(Transform2D);
|
||||
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::PLANE: {
|
||||
SET_FROM_STRUCT(Plane);
|
||||
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::QUAT: {
|
||||
SET_FROM_STRUCT(Quat);
|
||||
GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::AABB: {
|
||||
SET_FROM_STRUCT(AABB);
|
||||
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::BASIS: {
|
||||
SET_FROM_STRUCT(Basis);
|
||||
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::TRANSFORM: {
|
||||
SET_FROM_STRUCT(Transform);
|
||||
GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::COLOR: {
|
||||
SET_FROM_STRUCT(Color);
|
||||
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::NODE_PATH: {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
|
||||
|
@ -418,107 +332,41 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
|
|||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::POOL_BYTE_ARRAY: {
|
||||
SET_FROM_ARRAY(PoolByteArray);
|
||||
MonoArray *managed = GDMonoMarshal::PoolByteArray_to_mono_array(p_value.operator ::PoolByteArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::POOL_INT_ARRAY: {
|
||||
SET_FROM_ARRAY(PoolIntArray);
|
||||
MonoArray *managed = GDMonoMarshal::PoolIntArray_to_mono_array(p_value.operator ::PoolIntArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::POOL_REAL_ARRAY: {
|
||||
SET_FROM_ARRAY(PoolRealArray);
|
||||
MonoArray *managed = GDMonoMarshal::PoolRealArray_to_mono_array(p_value.operator ::PoolRealArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::POOL_STRING_ARRAY: {
|
||||
SET_FROM_ARRAY(PoolStringArray);
|
||||
MonoArray *managed = GDMonoMarshal::PoolStringArray_to_mono_array(p_value.operator ::PoolStringArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::POOL_VECTOR2_ARRAY: {
|
||||
SET_FROM_ARRAY(PoolVector2Array);
|
||||
MonoArray *managed = GDMonoMarshal::PoolVector2Array_to_mono_array(p_value.operator ::PoolVector2Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::POOL_VECTOR3_ARRAY: {
|
||||
SET_FROM_ARRAY(PoolVector3Array);
|
||||
MonoArray *managed = GDMonoMarshal::PoolVector3Array_to_mono_array(p_value.operator ::PoolVector3Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::POOL_COLOR_ARRAY: {
|
||||
SET_FROM_ARRAY(PoolColorArray);
|
||||
MonoArray *managed = GDMonoMarshal::PoolColorArray_to_mono_array(p_value.operator ::PoolColorArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case MONO_TYPE_GENERICINST: {
|
||||
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type.type_class->get_mono_type());
|
||||
|
||||
// Godot.Collections.Dictionary<TKey, TValue>
|
||||
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), type.type_class);
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// Godot.Collections.Array<T>
|
||||
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), type.type_class);
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// System.Collections.Generic.Dictionary<TKey, TValue>
|
||||
if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) {
|
||||
MonoReflectionType *key_reftype = nullptr;
|
||||
MonoReflectionType *value_reftype = nullptr;
|
||||
GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
|
||||
MonoObject *managed = GDMonoMarshal::Dictionary_to_system_generic_dict(p_value.operator Dictionary(),
|
||||
type.type_class, key_reftype, value_reftype);
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// System.Collections.Generic.List<T>
|
||||
if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) {
|
||||
MonoReflectionType *elem_reftype = nullptr;
|
||||
GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
|
||||
MonoObject *managed = GDMonoMarshal::Array_to_system_generic_list(p_value.operator Array(),
|
||||
type.type_class, elem_reftype);
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// IDictionary<TKey, TValue>
|
||||
if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) {
|
||||
MonoReflectionType *key_reftype;
|
||||
MonoReflectionType *value_reftype;
|
||||
GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
|
||||
GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype);
|
||||
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), godot_dict_class);
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// ICollection<T> or IEnumerable<T>
|
||||
if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) {
|
||||
MonoReflectionType *elem_reftype;
|
||||
GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
|
||||
GDMonoClass *godot_array_class = GDMonoUtils::Marshal::make_generic_array_type(elem_reftype);
|
||||
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), godot_array_class);
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
break;
|
||||
}
|
||||
|
||||
// GodotObject
|
||||
GDMonoClass *type_class = type.type_class;
|
||||
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
|
||||
MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
ERR_PRINT("Attempted to set the value of a field of unexpected type encoding: " + itos(type.type_encoding) + ".");
|
||||
} break;
|
||||
}
|
||||
|
||||
#undef SET_FROM_ARRAY_AND_BREAK
|
||||
#undef SET_FROM_STRUCT_AND_BREAK
|
||||
}
|
||||
|
||||
MonoObject *GDMonoField::get_value(MonoObject *p_object) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -103,15 +103,40 @@ _FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) {
|
|||
|
||||
// Variant
|
||||
|
||||
MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type);
|
||||
MonoObject *variant_to_mono_object(const Variant *p_var);
|
||||
size_t variant_get_managed_unboxed_size(const ManagedType &p_type);
|
||||
void *variant_to_managed_unboxed(const Variant &p_var, const ManagedType &p_type, void *r_buffer, unsigned int &r_offset);
|
||||
MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_type);
|
||||
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var) {
|
||||
return variant_to_mono_object(&p_var);
|
||||
MonoObject *variant_to_mono_object(const Variant &p_var);
|
||||
MonoArray *variant_to_mono_array(const Variant &p_var, GDMonoClass *p_type_class);
|
||||
MonoObject *variant_to_mono_object_of_class(const Variant &p_var, GDMonoClass *p_type_class);
|
||||
MonoObject *variant_to_mono_object_of_genericinst(const Variant &p_var, GDMonoClass *p_type_class);
|
||||
MonoString *variant_to_mono_string(const Variant &p_var);
|
||||
|
||||
// These overloads were added to avoid passing a `const Variant *` to the `const Variant &`
|
||||
// parameter. That would result in the `Variant(bool)` copy constructor being called as
|
||||
// pointers are implicitly converted to bool. Implicit conversions are f-ing evil.
|
||||
|
||||
_FORCE_INLINE_ void *variant_to_managed_unboxed(const Variant *p_var, const ManagedType &p_type, void *r_buffer, unsigned int &r_offset) {
|
||||
return variant_to_managed_unboxed(*p_var, p_type, r_buffer, r_offset);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_type) {
|
||||
return variant_to_mono_object(&p_var, p_type);
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type) {
|
||||
return variant_to_mono_object(*p_var, p_type);
|
||||
}
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant *p_var) {
|
||||
return variant_to_mono_object(*p_var);
|
||||
}
|
||||
_FORCE_INLINE_ MonoArray *variant_to_mono_array(const Variant *p_var, GDMonoClass *p_type_class) {
|
||||
return variant_to_mono_array(*p_var, p_type_class);
|
||||
}
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object_of_class(const Variant *p_var, GDMonoClass *p_type_class) {
|
||||
return variant_to_mono_object_of_class(*p_var, p_type_class);
|
||||
}
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object_of_genericinst(const Variant *p_var, GDMonoClass *p_type_class) {
|
||||
return variant_to_mono_object_of_genericinst(*p_var, p_type_class);
|
||||
}
|
||||
_FORCE_INLINE_ MonoString *variant_to_mono_string(const Variant *p_var) {
|
||||
return variant_to_mono_string(*p_var);
|
||||
}
|
||||
|
||||
Variant mono_object_to_variant(MonoObject *p_obj);
|
||||
|
@ -133,7 +158,7 @@ Variant system_generic_list_to_Array_variant(MonoObject *p_obj, GDMonoClass *p_c
|
|||
// Array
|
||||
|
||||
MonoArray *Array_to_mono_array(const Array &p_array);
|
||||
MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class);
|
||||
MonoArray *Array_to_mono_array(const Array &p_array, MonoClass *p_array_type_class);
|
||||
Array mono_array_to_Array(MonoArray *p_array);
|
||||
|
||||
// PoolIntArray
|
||||
|
|
|
@ -75,6 +75,10 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) {
|
|||
// clear the cache
|
||||
method_info_fetched = false;
|
||||
method_info = MethodInfo();
|
||||
|
||||
for (int i = 0; i < params_count; i++) {
|
||||
params_buffer_size += GDMonoMarshal::variant_get_managed_unboxed_size(param_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GDMonoClass *GDMonoMethod::get_enclosing_class() const {
|
||||
|
@ -102,50 +106,42 @@ 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) {
|
||||
void **params = (void **)alloca(params_count * sizeof(void *));
|
||||
uint8_t *buffer = (uint8_t *)alloca(params_buffer_size);
|
||||
unsigned int offset = 0;
|
||||
|
||||
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);
|
||||
params[i] = GDMonoMarshal::variant_to_managed_unboxed(p_params[i], param_types[i], buffer + offset, offset);
|
||||
}
|
||||
|
||||
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(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);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
ret = GDMonoUtils::runtime_invoke(mono_method, p_object, NULL, &exc);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
class GDMonoMethod : public IMonoClassMember {
|
||||
StringName name;
|
||||
|
||||
int params_count;
|
||||
uint16_t params_count;
|
||||
unsigned int params_buffer_size;
|
||||
ManagedType return_type;
|
||||
Vector<ManagedType> param_types;
|
||||
|
||||
|
@ -70,14 +71,14 @@ public:
|
|||
virtual MonoObject *get_attribute(GDMonoClass *p_attr_class) GD_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_ uint16_t 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;
|
||||
|
|
|
@ -143,10 +143,9 @@ bool GDMonoProperty::has_setter() {
|
|||
|
||||
void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) {
|
||||
MonoMethod *prop_method = mono_property_get_set_method(mono_property);
|
||||
MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1);
|
||||
mono_array_setref(params, 0, p_value);
|
||||
void *params[1] = { p_value };
|
||||
MonoException *exc = NULL;
|
||||
GDMonoUtils::runtime_invoke_array(prop_method, p_object, params, &exc);
|
||||
GDMonoUtils::runtime_invoke(prop_method, p_object, params, &exc);
|
||||
if (exc) {
|
||||
if (r_exc) {
|
||||
*r_exc = exc;
|
||||
|
|
|
@ -460,13 +460,6 @@ MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, M
|
|||
return ret;
|
||||
}
|
||||
|
||||
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc) {
|
||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||
MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)r_exc);
|
||||
GD_MONO_END_RUNTIME_INVOKE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc) {
|
||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||
MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)r_exc);
|
||||
|
|
|
@ -135,7 +135,6 @@ _FORCE_INLINE_ int &get_runtime_invoke_count_ref() {
|
|||
}
|
||||
|
||||
MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc);
|
||||
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc);
|
||||
|
||||
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc);
|
||||
|
||||
|
|
|
@ -88,11 +88,15 @@ Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argc
|
|||
set_completed(true);
|
||||
|
||||
int signal_argc = p_argcount - 1;
|
||||
MonoArray *signal_args = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), signal_argc);
|
||||
MonoArray *signal_args = NULL;
|
||||
|
||||
for (int i = 0; i < signal_argc; i++) {
|
||||
MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]);
|
||||
mono_array_setref(signal_args, i, boxed);
|
||||
if (signal_argc > 0) {
|
||||
signal_args = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), signal_argc);
|
||||
|
||||
for (int i = 0; i < signal_argc; i++) {
|
||||
MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]);
|
||||
mono_array_setref(signal_args, i, boxed);
|
||||
}
|
||||
}
|
||||
|
||||
MonoException *exc = NULL;
|
||||
|
|
Loading…
Reference in a new issue