diff options
Diffstat (limited to 'core/extension')
| -rw-r--r-- | core/extension/extension_api_dump.cpp | 172 | ||||
| -rw-r--r-- | core/extension/gdnative_interface.cpp | 219 | ||||
| -rw-r--r-- | core/extension/gdnative_interface.h | 37 | ||||
| -rw-r--r-- | core/extension/native_extension.cpp | 32 | ||||
| -rw-r--r-- | core/extension/native_extension.h | 8 | ||||
| -rw-r--r-- | core/extension/native_extension_manager.cpp | 19 | ||||
| -rw-r--r-- | core/extension/native_extension_manager.h | 3 |
7 files changed, 391 insertions, 99 deletions
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 660e215478..a8547a0090 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -38,6 +38,32 @@ #ifdef TOOLS_ENABLED +static String get_type_name(const PropertyInfo &p_info) { + if (p_info.type == Variant::INT && (p_info.hint == PROPERTY_HINT_INT_IS_POINTER)) { + if (p_info.hint_string == "") { + return "void*"; + } else { + return p_info.hint_string + "*"; + } + } + if (p_info.type == Variant::INT && (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM)) { + return String("enum::") + String(p_info.class_name); + } + if (p_info.class_name != StringName()) { + return p_info.class_name; + } + if (p_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { + return p_info.hint_string; + } + if (p_info.type == Variant::NIL && (p_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT)) { + return "Variant"; + } + if (p_info.type == Variant::NIL) { + return "void"; + } + return Variant::get_type_name(p_info.type); +} + Dictionary NativeExtensionAPIDump::generate_extension_api() { Dictionary api_dump; @@ -60,20 +86,38 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { const uint32_t vec3_elems = 3; const uint32_t ptrsize_32 = 4; - const uint32_t ptrsize_64 = 4; + const uint32_t ptrsize_64 = 8; static const char *build_config_name[4] = { "float_32", "float_64", "double_32", "double_64" }; { //type sizes - struct { + constexpr struct { Variant::Type type; uint32_t size_32_bits_real_float; uint32_t size_64_bits_real_float; uint32_t size_32_bits_real_double; uint32_t size_64_bits_real_double; + + // For compile-time size check. + constexpr uint32_t operator[](int index) const { + switch (index) { +#ifndef REAL_T_IS_DOUBLE + case sizeof(uint32_t): + return size_32_bits_real_float; + case sizeof(uint64_t): + return size_64_bits_real_float; +#else // REAL_T_IS_DOUBLE + case sizeof(uint32_t): + return size_32_bits_real_double; + case sizeof(uint64_t): + return size_64_bits_real_double; +#endif + } + return -1; + } } type_size_array[Variant::VARIANT_MAX + 1] = { { Variant::NIL, 0, 0, 0, 0 }, - { Variant::BOOL, sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t) }, + { Variant::BOOL, sizeof(uint8_t), sizeof(uint8_t), sizeof(uint8_t), sizeof(uint8_t) }, { Variant::INT, sizeof(int64_t), sizeof(int64_t), sizeof(int64_t), sizeof(int64_t) }, { Variant::FLOAT, sizeof(double), sizeof(double), sizeof(double), sizeof(double) }, { Variant::STRING, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, @@ -98,25 +142,62 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { { Variant::SIGNAL, sizeof(Signal), sizeof(Signal), sizeof(Signal), sizeof(Signal) }, // Hardcoded align. { Variant::DICTIONARY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, { Variant::ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_BYTE_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_INT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_INT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_FLOAT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_FLOAT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_STRING_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_VECTOR2_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_VECTOR3_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, - { Variant::PACKED_COLOR_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 }, + { Variant::PACKED_BYTE_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_INT32_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_INT64_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_FLOAT32_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_FLOAT64_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_STRING_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_VECTOR2_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_VECTOR3_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_COLOR_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, { Variant::VARIANT_MAX, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(double) * 4, sizeof(uint64_t) + sizeof(double) * 4 }, }; + // Validate sizes at compile time for the current build configuration. + static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDNativeBool), "Size of bool mismatch"); + static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDNativeInt), "Size of int mismatch"); + static_assert(type_size_array[Variant::FLOAT][sizeof(void *)] == sizeof(double), "Size of float mismatch"); + static_assert(type_size_array[Variant::STRING][sizeof(void *)] == sizeof(String), "Size of String mismatch"); + static_assert(type_size_array[Variant::VECTOR2][sizeof(void *)] == sizeof(Vector2), "Size of Vector2 mismatch"); + static_assert(type_size_array[Variant::VECTOR2I][sizeof(void *)] == sizeof(Vector2i), "Size of Vector2i mismatch"); + static_assert(type_size_array[Variant::RECT2][sizeof(void *)] == sizeof(Rect2), "Size of Rect2 mismatch"); + static_assert(type_size_array[Variant::RECT2I][sizeof(void *)] == sizeof(Rect2i), "Size of Rect2i mismatch"); + static_assert(type_size_array[Variant::VECTOR3][sizeof(void *)] == sizeof(Vector3), "Size of Vector3 mismatch"); + static_assert(type_size_array[Variant::VECTOR3I][sizeof(void *)] == sizeof(Vector3i), "Size of Vector3i mismatch"); + static_assert(type_size_array[Variant::TRANSFORM2D][sizeof(void *)] == sizeof(Transform2D), "Size of Transform2D mismatch"); + static_assert(type_size_array[Variant::PLANE][sizeof(void *)] == sizeof(Plane), "Size of Plane mismatch"); + static_assert(type_size_array[Variant::QUATERNION][sizeof(void *)] == sizeof(Quaternion), "Size of Quaternion mismatch"); + static_assert(type_size_array[Variant::AABB][sizeof(void *)] == sizeof(AABB), "Size of AABB mismatch"); + static_assert(type_size_array[Variant::BASIS][sizeof(void *)] == sizeof(Basis), "Size of Basis mismatch"); + static_assert(type_size_array[Variant::TRANSFORM3D][sizeof(void *)] == sizeof(Transform3D), "Size of Transform3D mismatch"); + static_assert(type_size_array[Variant::COLOR][sizeof(void *)] == sizeof(Color), "Size of Color mismatch"); + static_assert(type_size_array[Variant::STRING_NAME][sizeof(void *)] == sizeof(StringName), "Size of StringName mismatch"); + static_assert(type_size_array[Variant::NODE_PATH][sizeof(void *)] == sizeof(NodePath), "Size of NodePath mismatch"); + static_assert(type_size_array[Variant::RID][sizeof(void *)] == sizeof(RID), "Size of RID mismatch"); + static_assert(type_size_array[Variant::OBJECT][sizeof(void *)] == sizeof(Object *), "Size of Object mismatch"); + static_assert(type_size_array[Variant::CALLABLE][sizeof(void *)] == sizeof(Callable), "Size of Callable mismatch"); + static_assert(type_size_array[Variant::SIGNAL][sizeof(void *)] == sizeof(Signal), "Size of Signal mismatch"); + static_assert(type_size_array[Variant::DICTIONARY][sizeof(void *)] == sizeof(Dictionary), "Size of Dictionary mismatch"); + static_assert(type_size_array[Variant::ARRAY][sizeof(void *)] == sizeof(Array), "Size of Array mismatch"); + static_assert(type_size_array[Variant::PACKED_BYTE_ARRAY][sizeof(void *)] == sizeof(PackedByteArray), "Size of PackedByteArray mismatch"); + static_assert(type_size_array[Variant::PACKED_INT32_ARRAY][sizeof(void *)] == sizeof(PackedInt32Array), "Size of PackedInt32Array mismatch"); + static_assert(type_size_array[Variant::PACKED_INT64_ARRAY][sizeof(void *)] == sizeof(PackedInt64Array), "Size of PackedInt64Array mismatch"); + static_assert(type_size_array[Variant::PACKED_FLOAT32_ARRAY][sizeof(void *)] == sizeof(PackedFloat32Array), "Size of PackedFloat32Array mismatch"); + static_assert(type_size_array[Variant::PACKED_FLOAT64_ARRAY][sizeof(void *)] == sizeof(PackedFloat64Array), "Size of PackedFloat64Array mismatch"); + static_assert(type_size_array[Variant::PACKED_STRING_ARRAY][sizeof(void *)] == sizeof(PackedStringArray), "Size of PackedStringArray mismatch"); + static_assert(type_size_array[Variant::PACKED_VECTOR2_ARRAY][sizeof(void *)] == sizeof(PackedVector2Array), "Size of PackedVector2Array mismatch"); + static_assert(type_size_array[Variant::PACKED_VECTOR3_ARRAY][sizeof(void *)] == sizeof(PackedVector3Array), "Size of PackedVector3Array mismatch"); + static_assert(type_size_array[Variant::PACKED_COLOR_ARRAY][sizeof(void *)] == sizeof(PackedColorArray), "Size of PackedColorArray mismatch"); + static_assert(type_size_array[Variant::VARIANT_MAX][sizeof(void *)] == sizeof(Variant), "Size of Variant mismatch"); + Array core_type_sizes; for (int i = 0; i < 4; i++) { Dictionary d; d["build_configuration"] = build_config_name[i]; Array sizes; - for (int j = 0; j < Variant::VARIANT_MAX; j++) { + for (int j = 0; j <= Variant::VARIANT_MAX; j++) { Variant::Type t = type_size_array[j].type; String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t); Dictionary d2; @@ -356,6 +437,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { d["indexing_return_type"] = index_type == Variant::NIL ? String("Variant") : Variant::get_type_name(index_type); } + d["is_keyed"] = Variant::ValidatedKeyedSetter(type); + { //members Array members; @@ -403,6 +486,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) { d2["right_type"] = Variant::get_type_name(Variant::Type(j)); } + d2["return_type"] = Variant::get_type_name(Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j))); operators.push_back(d2); } } @@ -482,6 +566,10 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { d["constructors"] = constructors; } } + { + //destructor + d["has_destructor"] = Variant::has_destructor(type); + } builtins.push_back(d); } @@ -572,7 +660,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { ClassDB::get_method_list(class_name, &method_list, true); for (const MethodInfo &F : method_list) { StringName method_name = F.name; - if (F.flags & METHOD_FLAG_VIRTUAL) { + if ((F.flags & METHOD_FLAG_VIRTUAL) && !(F.flags & METHOD_FLAG_OBJECT_CORE)) { //virtual method const MethodInfo &mi = F; Dictionary d2; @@ -590,16 +678,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { if (i >= 0) { d3["name"] = pinfo.name; } - if (pinfo.class_name != StringName()) { - d3["type"] = String(pinfo.class_name); - } else { - Variant::Type type = pinfo.type; - if (type == Variant::NIL) { - d3["type"] = "Variant"; - } else { - d3["type"] = Variant::get_type_name(type); - } - } + + d3["type"] = get_type_name(pinfo); if (i == -1) { d2["return_value"] = d3; @@ -641,16 +721,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { if (i >= 0) { d3["name"] = pinfo.name; } - if (pinfo.class_name != StringName()) { - d3["type"] = String(pinfo.class_name); - } else { - Variant::Type type = pinfo.type; - if (type == Variant::NIL) { - d3["type"] = "Variant"; - } else { - d3["type"] = Variant::get_type_name(type); - } - } + d3["type"] = get_type_name(pinfo); if (method->get_argument_meta(i) > 0) { static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" }; @@ -697,14 +768,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { for (int i = 0; i < F.arguments.size(); i++) { Dictionary d3; d3["name"] = F.arguments[i].name; - Variant::Type type = F.arguments[i].type; - if (F.arguments[i].class_name != StringName()) { - d3["type"] = String(F.arguments[i].class_name); - } else if (type == Variant::NIL) { - d3["type"] = "Variant"; - } else { - d3["type"] = Variant::get_type_name(type); - } + d3["type"] = get_type_name(F.arguments[i]); arguments.push_back(d3); } if (arguments.size()) { @@ -732,16 +796,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { } StringName property_name = F.name; Dictionary d2; + d2["type"] = get_type_name(F); d2["name"] = String(property_name); - - if (F.class_name != StringName()) { - d2["type"] = String(F.class_name); - } else if (F.type == Variant::NIL && F.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { - d2["type"] = "Variant"; - } else { - d2["type"] = Variant::get_type_name(F.type); - } - d2["setter"] = ClassDB::get_property_setter(class_name, F.name); d2["getter"] = ClassDB::get_property_getter(class_name, F.name); d2["index"] = ClassDB::get_property_index(class_name, F.name); @@ -782,6 +838,20 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { } } + { + Array native_structures; + + { + Dictionary d; + d["name"] = "AudioFrame"; + d["format"] = "float left,float right"; + + native_structures.push_back(d); + } + + api_dump["native_structures"] = native_structures; + } + return api_dump; } diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index 88fff342ee..de107b4156 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -74,8 +74,6 @@ static void gdnative_variant_destroy(GDNativeVariantPtr p_self) { // variant type -#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) - static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { Variant *self = (Variant *)p_self; const StringName *method = (const StringName *)p_method; @@ -83,7 +81,7 @@ static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStrin Variant ret; Callable::CallError error; self->call(*method, args, p_argcount, ret, error); - memnew_placement_custom(r_return, Variant, Variant(ret)); + memnew_placement(r_return, Variant(ret)); if (r_error) { r_error->error = (GDNativeCallErrorType)(error.error); @@ -99,7 +97,7 @@ static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNat Variant ret; Callable::CallError error; Variant::call_static(type, *method, args, p_argcount, ret, error); - memnew_placement_custom(r_return, Variant, Variant(ret)); + memnew_placement(r_return, Variant(ret)); if (r_error) { r_error->error = (GDNativeCallErrorType)error.error; @@ -164,7 +162,7 @@ static void gdnative_variant_get(const GDNativeVariantPtr p_self, const GDNative const Variant *key = (const Variant *)p_key; bool valid; - memnew_placement_custom(r_ret, Variant, Variant(self->get(*key, &valid))); + memnew_placement(r_ret, Variant(self->get(*key, &valid))); *r_valid = valid; } @@ -173,7 +171,7 @@ static void gdnative_variant_get_named(const GDNativeVariantPtr p_self, const GD const StringName *key = (const StringName *)p_key; bool valid; - memnew_placement_custom(r_ret, Variant, Variant(self->get_named(*key, valid))); + memnew_placement(r_ret, Variant(self->get_named(*key, valid))); *r_valid = valid; } @@ -182,7 +180,7 @@ static void gdnative_variant_get_keyed(const GDNativeVariantPtr p_self, const GD const Variant *key = (const Variant *)p_key; bool valid; - memnew_placement_custom(r_ret, Variant, Variant(self->get_keyed(*key, valid))); + memnew_placement(r_ret, Variant(self->get_keyed(*key, valid))); *r_valid = valid; } @@ -191,7 +189,7 @@ static void gdnative_variant_get_indexed(const GDNativeVariantPtr p_self, GDNati bool valid; bool oob; - memnew_placement_custom(r_ret, Variant, Variant(self->get_indexed(p_index, valid, oob))); + memnew_placement(r_ret, Variant(self->get_indexed(p_index, valid, oob))); *r_valid = valid; *r_oob = oob; } @@ -222,7 +220,7 @@ static void gdnative_variant_iter_get(const GDNativeVariantPtr p_self, GDNativeV Variant *iter = (Variant *)r_iter; bool valid; - memnew_placement_custom(r_ret, Variant, Variant(self->iter_next(*iter, valid))); + memnew_placement(r_ret, Variant(self->iter_next(*iter, valid))); *r_valid = valid; } @@ -254,12 +252,12 @@ static void gdnative_variant_interpolate(const GDNativeVariantPtr p_a, const GDN static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) { const Variant *self = (const Variant *)p_self; - memnew_placement_custom(r_ret, Variant, Variant(self->duplicate(p_deep))); + memnew_placement(r_ret, Variant(self->duplicate(p_deep))); } static void gdnative_variant_stringify(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret) { const Variant *self = (const Variant *)p_self; - memnew_placement_custom(r_ret, String, String(*self)); + memnew_placement(r_ret, String(*self)); } static GDNativeVariantType gdnative_variant_get_type(const GDNativeVariantPtr p_self) { @@ -288,7 +286,7 @@ static GDNativeBool gdnative_variant_has_key(const GDNativeVariantPtr p_self, co static void gdnative_variant_get_type_name(GDNativeVariantType p_type, GDNativeStringPtr r_ret) { String name = Variant::get_type_name((Variant::Type)p_type); - memnew_placement_custom(r_ret, String, String(name)); + memnew_placement(r_ret, String(name)); } static GDNativeBool gdnative_variant_can_convert(GDNativeVariantType p_from, GDNativeVariantType p_to) { @@ -299,6 +297,161 @@ static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_fr return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to); } +// Variant interaction. +static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_constructor(GDNativeVariantType p_type) { + switch (p_type) { + case GDNATIVE_VARIANT_TYPE_BOOL: + return VariantTypeConstructor<bool>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_INT: + return VariantTypeConstructor<int64_t>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_FLOAT: + return VariantTypeConstructor<double>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_STRING: + return VariantTypeConstructor<String>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_VECTOR2: + return VariantTypeConstructor<Vector2>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_VECTOR2I: + return VariantTypeConstructor<Vector2i>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_RECT2: + return VariantTypeConstructor<Rect2>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_RECT2I: + return VariantTypeConstructor<Rect2i>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_VECTOR3: + return VariantTypeConstructor<Vector3>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_VECTOR3I: + return VariantTypeConstructor<Vector3i>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: + return VariantTypeConstructor<Transform2D>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PLANE: + return VariantTypeConstructor<Plane>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_QUATERNION: + return VariantTypeConstructor<Quaternion>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_AABB: + return VariantTypeConstructor<AABB>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_BASIS: + return VariantTypeConstructor<Basis>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: + return VariantTypeConstructor<Transform3D>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_COLOR: + return VariantTypeConstructor<Color>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_STRING_NAME: + return VariantTypeConstructor<StringName>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_NODE_PATH: + return VariantTypeConstructor<NodePath>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_RID: + return VariantTypeConstructor<RID>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_OBJECT: + return VariantTypeConstructor<Object *>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_CALLABLE: + return VariantTypeConstructor<Callable>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_SIGNAL: + return VariantTypeConstructor<Signal>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_DICTIONARY: + return VariantTypeConstructor<Dictionary>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_ARRAY: + return VariantTypeConstructor<Array>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY: + return VariantTypeConstructor<PackedByteArray>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY: + return VariantTypeConstructor<PackedInt32Array>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY: + return VariantTypeConstructor<PackedInt64Array>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: + return VariantTypeConstructor<PackedFloat32Array>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: + return VariantTypeConstructor<PackedFloat64Array>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY: + return VariantTypeConstructor<PackedStringArray>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: + return VariantTypeConstructor<PackedVector2Array>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: + return VariantTypeConstructor<PackedVector3Array>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY: + return VariantTypeConstructor<PackedColorArray>::variant_from_type; + case GDNATIVE_VARIANT_TYPE_NIL: + case GDNATIVE_VARIANT_TYPE_VARIANT_MAX: + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); + } + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); +} + +static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_constructor(GDNativeVariantType p_type) { + switch (p_type) { + case GDNATIVE_VARIANT_TYPE_BOOL: + return VariantTypeConstructor<bool>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_INT: + return VariantTypeConstructor<int64_t>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_FLOAT: + return VariantTypeConstructor<double>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_STRING: + return VariantTypeConstructor<String>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_VECTOR2: + return VariantTypeConstructor<Vector2>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_VECTOR2I: + return VariantTypeConstructor<Vector2i>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_RECT2: + return VariantTypeConstructor<Rect2>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_RECT2I: + return VariantTypeConstructor<Rect2i>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_VECTOR3: + return VariantTypeConstructor<Vector3>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_VECTOR3I: + return VariantTypeConstructor<Vector3i>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: + return VariantTypeConstructor<Transform2D>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PLANE: + return VariantTypeConstructor<Plane>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_QUATERNION: + return VariantTypeConstructor<Quaternion>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_AABB: + return VariantTypeConstructor<AABB>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_BASIS: + return VariantTypeConstructor<Basis>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: + return VariantTypeConstructor<Transform3D>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_COLOR: + return VariantTypeConstructor<Color>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_STRING_NAME: + return VariantTypeConstructor<StringName>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_NODE_PATH: + return VariantTypeConstructor<NodePath>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_RID: + return VariantTypeConstructor<RID>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_OBJECT: + return VariantTypeConstructor<Object *>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_CALLABLE: + return VariantTypeConstructor<Callable>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_SIGNAL: + return VariantTypeConstructor<Signal>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_DICTIONARY: + return VariantTypeConstructor<Dictionary>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_ARRAY: + return VariantTypeConstructor<Array>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY: + return VariantTypeConstructor<PackedByteArray>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY: + return VariantTypeConstructor<PackedInt32Array>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY: + return VariantTypeConstructor<PackedInt64Array>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: + return VariantTypeConstructor<PackedFloat32Array>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: + return VariantTypeConstructor<PackedFloat64Array>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY: + return VariantTypeConstructor<PackedStringArray>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: + return VariantTypeConstructor<PackedVector2Array>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: + return VariantTypeConstructor<PackedVector3Array>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY: + return VariantTypeConstructor<PackedColorArray>::type_from_variant; + case GDNATIVE_VARIANT_TYPE_NIL: + case GDNATIVE_VARIANT_TYPE_VARIANT_MAX: + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); + } + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); +} + // ptrcalls static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) { return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b)); @@ -316,6 +469,9 @@ static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNative static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) { return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor); } +static GDNativePtrDestructor gdnative_variant_get_ptr_destructor(GDNativeVariantType p_type) { + return (GDNativePtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type)); +} static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) { memnew_placement(p_base, Variant); @@ -350,7 +506,7 @@ static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVa return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type)); } static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret) { - memnew_placement_custom(r_ret, Variant, Variant(Variant::get_constant_value(Variant::Type(p_type), p_constant))); + memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), p_constant))); } static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const char *p_function, GDNativeInt p_hash) { StringName function = p_function; @@ -507,7 +663,23 @@ static const char32_t *gdnative_string_operator_index_const(const GDNativeString /* OBJECT API */ -static void gdnative_object_method_bind_ptrcall(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) { +static void gdnative_object_method_bind_call(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { + MethodBind *mb = (MethodBind *)p_method_bind; + Object *o = (Object *)p_instance; + const Variant **args = (const Variant **)p_args; + Callable::CallError error; + + Variant ret = mb->call(o, args, p_arg_count, error); + memnew_placement(r_return, Variant(ret)); + + if (r_error) { + r_error->error = (GDNativeCallErrorType)(error.error); + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} + +static void gdnative_object_method_bind_ptrcall(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) { MethodBind *mb = (MethodBind *)p_method_bind; Object *o = (Object *)p_instance; mb->ptrcall(o, (const void **)p_args, p_ret); @@ -521,11 +693,16 @@ static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) { return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name)); } -static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks) { +static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) { Object *o = (Object *)p_instance; return o->get_instance_binding(p_token, p_callbacks); } +static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_instance, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) { + Object *o = (Object *)p_instance; + o->set_instance_binding(p_token, p_binding, p_callbacks); +} + static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) { return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id)); } @@ -626,15 +803,15 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) { gdni.variant_can_convert = gdnative_variant_can_convert; gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict; - //ptrcalls -#if 0 - GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type); - GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type); -#endif + gdni.get_variant_from_type_constructor = gdnative_get_variant_from_type_constructor; + gdni.get_variant_to_type_constructor = gdnative_get_type_from_variant_constructor; + + // ptrcalls. gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator; gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method; gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor; + gdni.variant_get_ptr_destructor = gdnative_variant_get_ptr_destructor; gdni.variant_construct = gdnative_variant_construct; gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter; gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter; @@ -668,10 +845,12 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) { /* OBJECT */ + gdni.object_method_bind_call = gdnative_object_method_bind_call; gdni.object_method_bind_ptrcall = gdnative_object_method_bind_ptrcall; gdni.object_destroy = gdnative_object_destroy; gdni.global_get_singleton = gdnative_global_get_singleton; gdni.object_get_instance_binding = gdnative_object_get_instance_binding; + gdni.object_set_instance_binding = gdnative_object_set_instance_binding; gdni.object_cast_to = gdnative_object_cast_to; gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id; diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 3e69a28d59..3a5b04429c 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -39,6 +39,11 @@ #include <stdint.h> #include <stdio.h> +#ifndef __cplusplus +typedef uint32_t char32_t; +typedef uint16_t char16_t; +#endif + #ifdef __cplusplus extern "C" { #endif @@ -140,12 +145,12 @@ typedef uint64_t GDObjectInstanceID; /* VARIANT DATA I/O */ typedef enum { - NATIVE_CALL_OK, - NATIVE_CALL_ERROR_INVALID_METHOD, - NATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */ - NATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */ - NATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */ - NATIVE_CALL_ERROR_INSTANCE_IS_NULL, + GDNATIVE_CALL_OK, + GDNATIVE_CALL_ERROR_INVALID_METHOD, + GDNATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */ + GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */ + GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */ + GDNATIVE_CALL_ERROR_INSTANCE_IS_NULL, } GDNativeCallErrorType; @@ -160,6 +165,7 @@ typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNative typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result); typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count); typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args); +typedef void (*GDNativePtrDestructor)(GDNativeTypePtr p_base); typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value); typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value); typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value); @@ -173,7 +179,7 @@ typedef GDNativeObjectPtr (*GDNativeClassConstructor)(); typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_instance); typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding); -typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_instance, GDNativeBool p_reference); +typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference); struct GDNativeInstanceBindingCallbacks { GDNativeInstanceBindingCreateCallback create_callback; @@ -206,6 +212,7 @@ typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_ typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); typedef GDExtensionClassInstancePtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata); typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); +typedef void (*GDNativeExtensionClassObjectInstance)(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance); typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name); typedef struct { @@ -219,7 +226,8 @@ typedef struct { GDNativeExtensionClassUnreference unreference_func; GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ - GDNativeExtensionClassGetVirtual get_firtual_func; + GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */ + GDNativeExtensionClassGetVirtual get_virtual_func; void *class_userdata; } GDNativeExtensionClassCreationInfo; @@ -256,8 +264,8 @@ typedef enum { GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE } GDNativeExtensionClassMethodArgumentMetadata; -typedef void (*GDNativeExtensionClassMethodCall)(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); -typedef void (*GDNativeExtensionClassMethodPtrCall)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); +typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); +typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); /* passing -1 as argument in the following functions refers to the return type */ typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument); @@ -339,6 +347,7 @@ typedef struct { GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b); GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash); GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor); + GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type); void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error); GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member); GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member); @@ -380,10 +389,12 @@ typedef struct { /* OBJECT */ - void (*object_method_bind_ptrcall)(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); + void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error); + void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); void (*object_destroy)(GDNativeObjectPtr p_o); GDNativeObjectPtr (*global_get_singleton)(const char *p_name); - void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks); + void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks); + void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks); GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag); GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); @@ -399,7 +410,7 @@ typedef struct { void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_enum_name, const char *p_class_name, const char *p_constant_name, uint32_t p_constant_value); + void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value); void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index 16bc28e0a2..a3cd7ca14c 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -29,11 +29,14 @@ /*************************************************************************/ #include "native_extension.h" +#include "core/config/project_settings.h" #include "core/io/config_file.h" #include "core/object/class_db.h" #include "core/object/method_bind.h" #include "core/os/os.h" +const char *NativeExtension::EXTENSION_LIST_CONFIG_FILE = "res://.godot/extension_list.cfg"; + class NativeExtensionMethodBind : public MethodBind { GDNativeExtensionClassMethodCall call_func; GDNativeExtensionClassMethodPtrCall ptrcall_func; @@ -68,8 +71,8 @@ public: virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { Variant ret; GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); - GDNativeCallError ce; - call_func(extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce); + GDNativeCallError ce{ GDNATIVE_CALL_OK, 0, 0 }; + call_func(method_userdata, extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce); r_error.error = Callable::CallError::Error(ce.error); r_error.argument = ce.argument; r_error.expected = ce.expected; @@ -78,7 +81,7 @@ public: virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug."); GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); - ptrcall_func(extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret); + ptrcall_func(method_userdata, extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret); } virtual bool is_vararg() const { @@ -91,6 +94,7 @@ public: get_argument_type_func = p_method_info->get_argument_type_func; get_argument_info_func = p_method_info->get_argument_info_func; get_argument_metadata_func = p_method_info->get_argument_metadata_func; + set_name(p_method_info->name); vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG; @@ -109,7 +113,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr NativeExtension *self = (NativeExtension *)p_library; StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(String(class_name).is_valid_identifier(), "Attempt to register extension clas '" + class_name + "', which is not a valid class identifier."); + ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier."); ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered."); Extension *parent_extension = nullptr; @@ -150,7 +154,9 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr extension->native_extension.unreference = p_extension_funcs->unreference_func; extension->native_extension.class_userdata = p_extension_funcs->class_userdata; extension->native_extension.create_instance = p_extension_funcs->create_instance_func; + extension->native_extension.set_object_instance = p_extension_funcs->object_instance_func; extension->native_extension.free_instance = p_extension_funcs->free_instance_func; + extension->native_extension.get_virtual = p_extension_funcs->get_virtual_func; ClassDB::register_extension_class(&extension->native_extension); } @@ -159,19 +165,20 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl StringName class_name = p_class_name; StringName method_name = p_method_info->name; - ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'."); //Extension *extension = &self->extension_classes[class_name]; NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info)); + method->set_instance_class(class_name); ClassDB::bind_method_custom(class_name, method); } -void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value) { +void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value) { NativeExtension *self = (NativeExtension *)p_library; StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'."); //Extension *extension = &self->extension_classes[class_name]; @@ -181,7 +188,7 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension NativeExtension *self = (NativeExtension *)p_library; StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'."); //Extension *extension = &self->extension_classes[class_name]; PropertyInfo pinfo; @@ -199,7 +206,7 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl NativeExtension *self = (NativeExtension *)p_library; StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'."); MethodInfo s; s.name = p_signal_name; @@ -220,7 +227,7 @@ void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLi NativeExtension *self = (NativeExtension *)p_library; StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'."); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'."); Extension *ext = &self->extension_classes[class_name]; ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it."); @@ -368,7 +375,7 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or } } - if (library_path != String()) { + if (library_path == String()) { if (r_error) { *r_error = ERR_FILE_NOT_FOUND; } @@ -381,7 +388,8 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or Ref<NativeExtension> lib; lib.instantiate(); - err = lib->open_library(library_path, entry_symbol); + String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path); + err = lib->open_library(abs_path, entry_symbol); if (r_error) { *r_error = err; diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h index 0a23848eb2..b661381d64 100644 --- a/core/extension/native_extension.h +++ b/core/extension/native_extension.h @@ -35,8 +35,8 @@ #include "core/io/resource_loader.h" #include "core/object/ref_counted.h" -class NativeExtension : public RefCounted { - GDCLASS(NativeExtension, RefCounted) +class NativeExtension : public Resource { + GDCLASS(NativeExtension, Resource) void *library = nullptr; // pointer if valid, @@ -48,7 +48,7 @@ class NativeExtension : public RefCounted { static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, uint32_t p_constant_value); + static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value); static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); @@ -60,6 +60,8 @@ protected: static void _bind_methods(); public: + static const char *EXTENSION_LIST_CONFIG_FILE; + Error open_library(const String &p_path, const String &p_entry_symbol); void close_library(); diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp index 7be2593845..8b7a9df4f1 100644 --- a/core/extension/native_extension_manager.cpp +++ b/core/extension/native_extension_manager.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "native_extension_manager.h" +#include "core/io/file_access.h" NativeExtensionManager::LoadStatus NativeExtensionManager::load_extension(const String &p_path) { if (native_extension_map.has(p_path)) { @@ -76,6 +77,11 @@ NativeExtensionManager::LoadStatus NativeExtensionManager::unload_extension(cons native_extension_map.erase(p_path); return LOAD_STATUS_OK; } + +bool NativeExtensionManager::is_extension_loaded(const String &p_path) const { + return native_extension_map.has(p_path); +} + Vector<String> NativeExtensionManager::get_loaded_extensions() const { Vector<String> ret; for (const Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) { @@ -105,6 +111,17 @@ void NativeExtensionManager::deinitialize_extensions(NativeExtension::Initializa level = int32_t(p_level) - 1; } +void NativeExtensionManager::load_extensions() { + FileAccessRef f = FileAccess::open(NativeExtension::EXTENSION_LIST_CONFIG_FILE, FileAccess::READ); + while (f && !f->eof_reached()) { + String s = f->get_line().strip_edges(); + if (s != String()) { + LoadStatus err = load_extension(s); + ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, "Error loading extension: " + s); + } + } +} + NativeExtensionManager *NativeExtensionManager::get_singleton() { return singleton; } @@ -112,6 +129,8 @@ void NativeExtensionManager::_bind_methods() { ClassDB::bind_method(D_METHOD("load_extension", "path"), &NativeExtensionManager::load_extension); ClassDB::bind_method(D_METHOD("reload_extension", "path"), &NativeExtensionManager::reload_extension); ClassDB::bind_method(D_METHOD("unload_extension", "path"), &NativeExtensionManager::unload_extension); + ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &NativeExtensionManager::is_extension_loaded); + ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &NativeExtensionManager::get_loaded_extensions); ClassDB::bind_method(D_METHOD("get_extension", "path"), &NativeExtensionManager::get_extension); diff --git a/core/extension/native_extension_manager.h b/core/extension/native_extension_manager.h index 78465bd5cf..89ccd155fe 100644 --- a/core/extension/native_extension_manager.h +++ b/core/extension/native_extension_manager.h @@ -55,6 +55,7 @@ public: LoadStatus load_extension(const String &p_path); LoadStatus reload_extension(const String &p_path); LoadStatus unload_extension(const String &p_path); + bool is_extension_loaded(const String &p_path) const; Vector<String> get_loaded_extensions() const; Ref<NativeExtension> get_extension(const String &p_path); @@ -63,6 +64,8 @@ public: static NativeExtensionManager *get_singleton(); + void load_extensions(); + NativeExtensionManager(); }; |
