From 0e81f89dd3ea7418573075a716dcdd94b73e8621 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Sat, 22 Oct 2022 13:46:59 +0200 Subject: [PATCH 1/7] Uses `StringName` in GDExtension perf critical instance creation & method/properties setter/getter --- binding_generator.py | 20 ++++++++++++----- godot-headers/godot/gdnative_interface.h | 22 +++++++++---------- include/godot_cpp/classes/wrapped.hpp | 28 ++++++++++++++---------- src/classes/wrapped.cpp | 10 ++++----- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 0bf46ea9..84e82028 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -687,20 +687,24 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl f"\t_method_bindings.destructor = internal::gdn_interface->variant_get_ptr_destructor({enum_type_name});" ) + result.append(f"StringName __name;") + if "methods" in builtin_api: for method in builtin_api["methods"]: # TODO: Add error check for hash mismatch. + result.append(f'\t__name = StringName("{method["name"]}");') result.append( - f'\t_method_bindings.method_{method["name"]} = internal::gdn_interface->variant_get_ptr_builtin_method({enum_type_name}, "{method["name"]}", {method["hash"]});' + f'\t_method_bindings.method_{method["name"]} = internal::gdn_interface->variant_get_ptr_builtin_method({enum_type_name}, (void *)&__name, {method["hash"]});' ) if "members" in builtin_api: for member in builtin_api["members"]: + result.append(f'\t__name = StringName("{member["name"]}");') result.append( - f'\t_method_bindings.member_{member["name"]}_setter = internal::gdn_interface->variant_get_ptr_setter({enum_type_name}, "{member["name"]}");' + f'\t_method_bindings.member_{member["name"]}_setter = internal::gdn_interface->variant_get_ptr_setter({enum_type_name}, (void *)&__name);' ) result.append( - f'\t_method_bindings.member_{member["name"]}_getter = internal::gdn_interface->variant_get_ptr_getter({enum_type_name}, "{member["name"]}");' + f'\t_method_bindings.member_{member["name"]}_getter = internal::gdn_interface->variant_get_ptr_getter({enum_type_name}, (void *)&__name);' ) if "indexing_return_type" in builtin_api: @@ -1292,8 +1296,9 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us if is_singleton: result.append(f"{class_name} *{class_name}::get_singleton() {{") + result.append(f'\tconst StringName __class_name = {class_name}::get_class_static();') result.append( - f'\tstatic GDNativeObjectPtr singleton_obj = internal::gdn_interface->global_get_singleton("{class_name}");' + f"\tstatic GDNativeObjectPtr singleton_obj = internal::gdn_interface->global_get_singleton((void *)&__class_name);" ) result.append("#ifdef DEBUG_ENABLED") result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);") @@ -1318,8 +1323,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append(method_signature + " {") # Method body. + result.append(f'\tconst StringName __class_name = {class_name}::get_class_static();') + result.append(f'\tconst StringName __method_name = "{method["name"]}";') result.append( - f'\tstatic GDNativeMethodBindPtr ___method_bind = internal::gdn_interface->classdb_get_method_bind("{class_name}", "{method["name"]}", {method["hash"]});' + f'\tstatic GDNativeMethodBindPtr ___method_bind = internal::gdn_interface->classdb_get_method_bind((void *)&__class_name, (void *)&__method_name, {method["hash"]});' ) method_call = "\t" has_return = "return_value" in method and method["return_value"]["type"] != "void" @@ -1566,8 +1573,9 @@ def generate_utility_functions(api, output_dir): # Function body. + source.append(f'\tconst StringName __function_name = "{function["name"]}";') source.append( - f'\tstatic GDNativePtrUtilityFunction ___function = internal::gdn_interface->variant_get_ptr_utility_function("{function["name"]}", {function["hash"]});' + f'\tstatic GDNativePtrUtilityFunction ___function = internal::gdn_interface->variant_get_ptr_utility_function((void *)&__function_name, {function["hash"]});' ) has_return = "return_type" in function and function["return_type"] != "void" if has_return: diff --git a/godot-headers/godot/gdnative_interface.h b/godot-headers/godot/gdnative_interface.h index 1ce50bc1..eaad1791 100644 --- a/godot-headers/godot/gdnative_interface.h +++ b/godot-headers/godot/gdnative_interface.h @@ -400,7 +400,7 @@ typedef struct { void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - uint64_t (*get_native_struct_size)(const char *p_name); + uint64_t (*get_native_struct_size)(const GDNativeStringNamePtr p_name); /* GODOT VARIANT */ @@ -443,19 +443,19 @@ typedef struct { GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type); GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type); 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); + GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const GDNativeStringNamePtr 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); + GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); + GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type); GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type); GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type); GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type); GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type); - void (*variant_get_constant_value)(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret); - GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const char *p_function, GDNativeInt p_hash); + void (*variant_get_constant_value)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret); + GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const GDNativeStringNamePtr p_function, GDNativeInt p_hash); /* extra utilities */ @@ -524,12 +524,12 @@ typedef struct { 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); + GDNativeObjectPtr (*global_get_singleton)(const GDNativeStringNamePtr p_name); 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); - void (*object_set_instance)(GDNativeObjectPtr p_o, const char *p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ + void (*object_set_instance)(GDNativeObjectPtr p_o, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag); GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); @@ -540,9 +540,9 @@ typedef struct { GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data); /* CLASSDB */ - GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ - GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash); - void *(*classdb_get_class_tag)(const char *p_classname); + GDNativeObjectPtr (*classdb_construct_object)(const GDNativeStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ + GDNativeMethodBindPtr (*classdb_get_method_bind)(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash); + void *(*classdb_get_class_tag)(const GDNativeStringNamePtr p_classname); /* CLASSDB EXTENSION */ diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index ce1bc51a..128e091f 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -49,7 +49,7 @@ class Wrapped { friend void postinitialize_handler(Wrapped *); protected: - virtual const char *_get_extension_class() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. + virtual const StringName *_get_extension_class() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const = 0; void _notification(int p_what){}; @@ -74,12 +74,13 @@ protected: void _postinitialize(); - Wrapped(const char *p_godot_class); + Wrapped(const StringName p_godot_class); Wrapped(GodotObject *p_godot_object); public: - static const char *get_class_static() { - return "Wrapped"; + static StringName get_class_static() { + static StringName string_name = StringName("Wrapped"); + return string_name; } uint64_t get_instance_id() const { @@ -105,8 +106,9 @@ private: friend class ::godot::ClassDB; \ \ protected: \ - virtual const char *_get_extension_class() const override { \ - return get_class_static(); \ + virtual const StringName *_get_extension_class() const override { \ + static StringName string_name = get_class_static(); \ + return &string_name; \ } \ \ virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override { \ @@ -164,11 +166,12 @@ public: initialized = true; \ } \ \ - static const char *get_class_static() { \ - return #m_class; \ + static StringName get_class_static() { \ + static StringName string_name = StringName(#m_class); \ + return string_name; \ } \ \ - static const char *get_parent_class_static() { \ + static StringName *get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ \ @@ -357,11 +360,12 @@ protected: public: \ static void initialize_class() {} \ \ - static const char *get_class_static() { \ - return #m_class; \ + static StringName get_class_static() { \ + static StringName string_name = StringName(#m_class); \ + return string_name; \ } \ \ - static const char *get_parent_class_static() { \ + static StringName get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ \ diff --git a/src/classes/wrapped.cpp b/src/classes/wrapped.cpp index a62edc4d..84ac3a47 100644 --- a/src/classes/wrapped.cpp +++ b/src/classes/wrapped.cpp @@ -36,20 +36,20 @@ namespace godot { -const char *Wrapped::_get_extension_class() const { +const StringName *Wrapped::_get_extension_class() const { return nullptr; } void Wrapped::_postinitialize() { - const char *extension_class = _get_extension_class(); + const StringName *extension_class = _get_extension_class(); if (extension_class) { - godot::internal::gdn_interface->object_set_instance(_owner, extension_class, this); + godot::internal::gdn_interface->object_set_instance(_owner, (void *)extension_class, this); } godot::internal::gdn_interface->object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks()); } -Wrapped::Wrapped(const char *p_godot_class) { - _owner = godot::internal::gdn_interface->classdb_construct_object(p_godot_class); +Wrapped::Wrapped(const StringName p_godot_class) { + _owner = godot::internal::gdn_interface->classdb_construct_object((void *)&p_godot_class); } Wrapped::Wrapped(GodotObject *p_godot_object) { From e24b6b0e517bbebe4ed98d9736c0c7219c418b99 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Sat, 22 Oct 2022 19:42:48 +0200 Subject: [PATCH 2/7] Use StringName in the whole GDExtension API instead of const char * --- binding_generator.py | 23 ++-- godot-headers/godot/gdnative_interface.h | 50 ++++----- include/godot_cpp/classes/ref.hpp | 8 +- include/godot_cpp/classes/wrapped.hpp | 17 ++- include/godot_cpp/core/binder_common.hpp | 4 +- include/godot_cpp/core/class_db.hpp | 76 +++++++------ include/godot_cpp/core/method_bind.hpp | 111 +++++++++---------- include/godot_cpp/core/object.hpp | 26 ++--- include/godot_cpp/core/property_info.hpp | 8 +- include/godot_cpp/core/type_info.hpp | 130 +++++++++++----------- src/classes/wrapped.cpp | 12 ++- src/core/class_db.cpp | 132 ++++++++++++----------- src/core/method_bind.cpp | 29 ++--- src/core/object.cpp | 6 +- 14 files changed, 318 insertions(+), 314 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 84e82028..33bd568e 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -394,9 +394,6 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append(f"class {class_name} {{") result.append(f"\tstatic constexpr size_t {snake_class_name}_SIZE = {size};") result.append(f"\tuint8_t opaque[{snake_class_name}_SIZE] = {{}};") - result.append( - f"\t_FORCE_INLINE_ GDNativeTypePtr _native_ptr() const {{ return const_cast(&opaque); }}" - ) result.append("") result.append("\tfriend class Variant;") @@ -446,6 +443,10 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("public:") + result.append( + f"\t_FORCE_INLINE_ GDNativeTypePtr _native_ptr() const {{ return const_cast(&opaque); }}" + ) + copy_constructor_index = -1 if "constructors" in builtin_api: @@ -694,17 +695,17 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl # TODO: Add error check for hash mismatch. result.append(f'\t__name = StringName("{method["name"]}");') result.append( - f'\t_method_bindings.method_{method["name"]} = internal::gdn_interface->variant_get_ptr_builtin_method({enum_type_name}, (void *)&__name, {method["hash"]});' + f'\t_method_bindings.method_{method["name"]} = internal::gdn_interface->variant_get_ptr_builtin_method({enum_type_name}, __name._native_ptr(), {method["hash"]});' ) if "members" in builtin_api: for member in builtin_api["members"]: result.append(f'\t__name = StringName("{member["name"]}");') result.append( - f'\t_method_bindings.member_{member["name"]}_setter = internal::gdn_interface->variant_get_ptr_setter({enum_type_name}, (void *)&__name);' + f'\t_method_bindings.member_{member["name"]}_setter = internal::gdn_interface->variant_get_ptr_setter({enum_type_name}, __name._native_ptr());' ) result.append( - f'\t_method_bindings.member_{member["name"]}_getter = internal::gdn_interface->variant_get_ptr_getter({enum_type_name}, (void *)&__name);' + f'\t_method_bindings.member_{member["name"]}_getter = internal::gdn_interface->variant_get_ptr_getter({enum_type_name}, __name._native_ptr());' ) if "indexing_return_type" in builtin_api: @@ -1296,9 +1297,9 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us if is_singleton: result.append(f"{class_name} *{class_name}::get_singleton() {{") - result.append(f'\tconst StringName __class_name = {class_name}::get_class_static();') + result.append(f"\tconst StringName __class_name = {class_name}::get_class_static();") result.append( - f"\tstatic GDNativeObjectPtr singleton_obj = internal::gdn_interface->global_get_singleton((void *)&__class_name);" + f"\tstatic GDNativeObjectPtr singleton_obj = internal::gdn_interface->global_get_singleton(__class_name._native_ptr());" ) result.append("#ifdef DEBUG_ENABLED") result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);") @@ -1323,10 +1324,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append(method_signature + " {") # Method body. - result.append(f'\tconst StringName __class_name = {class_name}::get_class_static();') + result.append(f"\tconst StringName __class_name = {class_name}::get_class_static();") result.append(f'\tconst StringName __method_name = "{method["name"]}";') result.append( - f'\tstatic GDNativeMethodBindPtr ___method_bind = internal::gdn_interface->classdb_get_method_bind((void *)&__class_name, (void *)&__method_name, {method["hash"]});' + f'\tstatic GDNativeMethodBindPtr ___method_bind = internal::gdn_interface->classdb_get_method_bind(__class_name._native_ptr(), __method_name._native_ptr(), {method["hash"]});' ) method_call = "\t" has_return = "return_value" in method and method["return_value"]["type"] != "void" @@ -1575,7 +1576,7 @@ def generate_utility_functions(api, output_dir): source.append(f'\tconst StringName __function_name = "{function["name"]}";') source.append( - f'\tstatic GDNativePtrUtilityFunction ___function = internal::gdn_interface->variant_get_ptr_utility_function((void *)&__function_name, {function["hash"]});' + f'\tstatic GDNativePtrUtilityFunction ___function = internal::gdn_interface->variant_get_ptr_utility_function(__function_name._native_ptr(), {function["hash"]});' ) has_return = "return_type" in function and function["return_type"] != "void" if has_return: diff --git a/godot-headers/godot/gdnative_interface.h b/godot-headers/godot/gdnative_interface.h index eaad1791..d99d6a92 100644 --- a/godot-headers/godot/gdnative_interface.h +++ b/godot-headers/godot/gdnative_interface.h @@ -202,21 +202,21 @@ typedef uint64_t (*GDNativeExtensionClassGetRID)(GDExtensionClassInstancePtr p_i typedef struct { GDNativeVariantType type; - const char *name; - const char *class_name; + GDNativeStringNamePtr name; + GDNativeStringNamePtr class_name; uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`) - const char *hint_string; + GDNativeStringPtr hint_string; uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`) } GDNativePropertyInfo; typedef struct { - const char *name; + GDNativeStringNamePtr name; GDNativePropertyInfo return_value; uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags` int32_t id; - GDNativePropertyInfo *arguments; + GDNativePropertyInfo *arguments; // array of `argument_count` size uint32_t argument_count; - GDNativeVariantPtr default_arguments; + GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size uint32_t default_argument_count; } GDNativeMethodInfo; @@ -231,7 +231,7 @@ typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_ typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); typedef GDNativeObjectPtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata); typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); -typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name); +typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const GDNativeStringNamePtr p_name); typedef struct { GDNativeBool is_virtual; @@ -284,24 +284,21 @@ typedef enum { 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); -typedef void (*GDNativeExtensionClassMethodGetArgumentInfo)(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info); -typedef GDNativeExtensionClassMethodArgumentMetadata (*GDNativeExtensionClassMethodGetArgumentMetadata)(void *p_method_userdata, int32_t p_argument); - typedef struct { - const char *name; + GDNativeStringNamePtr name; void *method_userdata; GDNativeExtensionClassMethodCall call_func; GDNativeExtensionClassMethodPtrCall ptrcall_func; uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags` uint32_t argument_count; GDNativeBool has_return_value; - GDNativeExtensionClassMethodGetArgumentType get_argument_type_func; - GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ - GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func; + GDNativePropertyInfo *return_value_info; // Ignored if `has_return_value` is false + GDNativeExtensionClassMethodArgumentMetadata return_value_metadata; // Ignored if `has_return_value` is false + /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ + GDNativePropertyInfo *aguments_info; // array of `argument_count` size + GDNativeExtensionClassMethodArgumentMetadata *aguments_metadata; // array of `argument_count` size uint32_t default_argument_count; - GDNativeVariantPtr *default_arguments; + GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size } GDNativeExtensionClassMethodInfo; /* SCRIPT INSTANCE EXTENSION */ @@ -312,7 +309,6 @@ typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScri typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list); -typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid); typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name); typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); @@ -349,7 +345,6 @@ typedef struct { GDNativeExtensionScriptInstanceGet get_func; GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func; GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func; - GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func; GDNativeExtensionScriptInstancePropertyCanRevert property_can_revert_func; GDNativeExtensionScriptInstancePropertyGetRevert property_get_revert_func; @@ -546,14 +541,15 @@ typedef struct { /* CLASSDB EXTENSION */ - 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_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); - 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_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix); - void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix); - 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. */ + // Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns + void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); + void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); + void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); + void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter); + void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix); + void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix); + void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); + void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ void (*get_library_path)(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path); diff --git a/include/godot_cpp/classes/ref.hpp b/include/godot_cpp/classes/ref.hpp index 16e418d6..21171d77 100644 --- a/include/godot_cpp/classes/ref.hpp +++ b/include/godot_cpp/classes/ref.hpp @@ -264,8 +264,8 @@ struct GetTypeInfo, typename EnableIf::value> static const GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_OBJECT; static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_OBJECT, T::get_class_static()); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::OBJECT, T::get_class_static()); } }; @@ -274,8 +274,8 @@ struct GetTypeInfo &, typename EnableIf static const GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_OBJECT; static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_OBJECT, T::get_class_static()); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::OBJECT, T::get_class_static()); } }; diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 128e091f..83c4cc30 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -49,7 +49,7 @@ class Wrapped { friend void postinitialize_handler(Wrapped *); protected: - virtual const StringName *_get_extension_class() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. + virtual const StringName *_get_extension_class_name() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const = 0; void _notification(int p_what){}; @@ -106,7 +106,7 @@ private: friend class ::godot::ClassDB; \ \ protected: \ - virtual const StringName *_get_extension_class() const override { \ + virtual const StringName *_get_extension_class_name() const override { \ static StringName string_name = get_class_static(); \ return &string_name; \ } \ @@ -171,7 +171,7 @@ public: return string_name; \ } \ \ - static StringName *get_parent_class_static() { \ + static StringName get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ \ @@ -223,10 +223,10 @@ public: cls->plist_size = 0; \ for (const ::godot::PropertyInfo &E : list) { \ cls->plist[cls->plist_size].type = static_cast(E.type); \ - cls->plist[cls->plist_size].name = _alloc_and_copy_cstr(E.name.utf8().get_data()); \ + cls->plist[cls->plist_size].name = E.name._native_ptr(); \ cls->plist[cls->plist_size].hint = E.hint; \ - cls->plist[cls->plist_size].hint_string = _alloc_and_copy_cstr(E.hint_string.utf8().get_data()); \ - cls->plist[cls->plist_size].class_name = _alloc_and_copy_cstr(E.class_name.utf8().get_data()); \ + cls->plist[cls->plist_size].hint_string = E.hint_string._native_ptr(); \ + cls->plist[cls->plist_size].class_name = E.class_name._native_ptr(); \ cls->plist[cls->plist_size].usage = E.usage; \ cls->plist_size++; \ } \ @@ -243,11 +243,6 @@ public: if (p_instance) { \ m_class *cls = reinterpret_cast(p_instance); \ ERR_FAIL_COND_MSG(cls->plist == nullptr, "Internal error, property list double free!"); \ - for (size_t i = 0; i < cls->plist_size; i++) { \ - memfree(const_cast(cls->plist[i].name)); \ - memfree(const_cast(cls->plist[i].class_name)); \ - memfree(const_cast(cls->plist[i].hint_string)); \ - } \ memfree(cls->plist); \ cls->plist = nullptr; \ cls->plist_size = 0; \ diff --git a/include/godot_cpp/core/binder_common.hpp b/include/godot_cpp/core/binder_common.hpp index b7ce35af..8bee243a 100644 --- a/include/godot_cpp/core/binder_common.hpp +++ b/include/godot_cpp/core/binder_common.hpp @@ -423,7 +423,7 @@ GDNativeVariantType call_get_argument_type(int p_arg) { } template -void call_get_argument_type_info_helper(int p_arg, int &index, GDNativePropertyInfo &info) { +void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) { if (p_arg == index) { info = GetTypeInfo::get_class_info(); } @@ -431,7 +431,7 @@ void call_get_argument_type_info_helper(int p_arg, int &index, GDNativePropertyI } template -void call_get_argument_type_info(int p_arg, GDNativePropertyInfo &info) { +void call_get_argument_type_info(int p_arg, PropertyInfo &info) { int index = 0; // I think rocket science is simpler than modern C++. using expand_type = int[]; diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 514a8008..f6fbd39f 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -44,22 +44,30 @@ #include #include +// Needed to use StringName as key in `std::unordered_map` +template <> +struct std::hash { + std::size_t operator()(godot::StringName const &s) const noexcept { + return s.hash(); + } +}; + namespace godot { #define DEFVAL(m_defval) (m_defval) struct MethodDefinition { - const char *name = nullptr; - std::list args; + StringName name; + std::list args; MethodDefinition() {} - MethodDefinition(const char *p_name) : + MethodDefinition(StringName p_name) : name(p_name) {} }; -MethodDefinition D_METHOD(const char *p_name); -MethodDefinition D_METHOD(const char *p_name, const char *p_arg1); +MethodDefinition D_METHOD(StringName p_name); +MethodDefinition D_METHOD(StringName p_name, StringName p_arg1); template -MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, Args... args) { +MethodDefinition D_METHOD(StringName p_name, StringName p_arg1, Args... args) { MethodDefinition md = D_METHOD(p_name, args...); md.args.push_front(p_arg1); return md; @@ -73,33 +81,33 @@ class ClassDB { public: struct PropertySetGet { int index; - const char *setter; - const char *getter; + StringName setter; + StringName getter; MethodBind *_setptr; MethodBind *_getptr; Variant::Type type; }; struct ClassInfo { - const char *name = nullptr; - const char *parent_name = nullptr; + StringName name; + StringName parent_name; GDNativeInitializationLevel level = GDNATIVE_INITIALIZATION_SCENE; - std::unordered_map method_map; - std::set signal_names; - std::unordered_map virtual_methods; - std::set property_names; - std::set constant_names; + std::unordered_map method_map; + std::set signal_names; + std::unordered_map virtual_methods; + std::set property_names; + std::set constant_names; // Pointer to the parent custom class, if any. Will be null if the parent class is a Godot class. ClassInfo *parent_ptr = nullptr; }; private: // This may only contain custom classes, not Godot classes - static std::unordered_map classes; + static std::unordered_map classes; static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount); static void initialize_class(const ClassInfo &cl); - static void bind_method_godot(const char *p_class_name, MethodBind *p_method); + static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method); static _FORCE_INLINE_ char *_alloc_and_copy_cstr(const char *p_str) { size_t size = strlen(p_str) + 1; @@ -121,21 +129,21 @@ public: static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args); template - static MethodBind *bind_static_method(const char *p_class, N p_method_name, M p_method, VarArgs... p_args); + static MethodBind *bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args); template - static MethodBind *bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector &p_default_args = std::vector{}, bool p_return_nil_is_variant = true); + static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector &p_default_args = std::vector{}, bool p_return_nil_is_variant = true); - static void add_property_group(const char *p_class, const char *p_name, const char *p_prefix); - static void add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix); - static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1); - static void add_signal(const char *p_class, const MethodInfo &p_signal); - static void bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield = false); - static void bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call); + static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix); + static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix); + static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1); + static void add_signal(const StringName &p_class, const MethodInfo &p_signal); + static void bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield = false); + static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDNativeExtensionClassCallVirtual p_call); - static MethodBind *get_method(const char *p_class, const char *p_method); + static MethodBind *get_method(const StringName &p_class, const StringName &p_method); - static GDNativeExtensionClassCallVirtual get_virtual_func(void *p_userdata, const char *p_name); + static GDNativeExtensionClassCallVirtual get_virtual_func(void *p_userdata, const GDNativeStringNamePtr p_name); static void initialize(GDNativeInitializationLevel p_level); static void deinitialize(GDNativeInitializationLevel p_level); @@ -165,7 +173,7 @@ void ClassDB::_register_class(bool p_virtual) { cl.name = T::get_class_static(); cl.parent_name = T::get_parent_class_static(); cl.level = current_level; - std::unordered_map::iterator parent_it = classes.find(cl.parent_name); + std::unordered_map::iterator parent_it = classes.find(cl.parent_name); if (parent_it != classes.end()) { // Assign parent if it is also a custom class cl.parent_ptr = &parent_it->second; @@ -190,10 +198,10 @@ void ClassDB::_register_class(bool p_virtual) { T::free, // GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ &ClassDB::get_virtual_func, // GDNativeExtensionClassGetVirtual get_virtual_func; nullptr, // GDNativeExtensionClassGetRID get_rid; - (void *)cl.name, // void *class_userdata; + (void *)&cl.name, // void *class_userdata; }; - internal::gdn_interface->classdb_register_extension_class(internal::library, cl.name, cl.parent_name, &class_info); + internal::gdn_interface->classdb_register_extension_class(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info); // call bind_methods etc. to register all members of the class T::initialize_class(); @@ -224,7 +232,7 @@ MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) } template -MethodBind *ClassDB::bind_static_method(const char *p_class, N p_method_name, M p_method, VarArgs... p_args) { +MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. const Variant *argptrs[sizeof...(p_args) + 1]; for (uint32_t i = 0; i < sizeof...(p_args); i++) { @@ -236,16 +244,16 @@ MethodBind *ClassDB::bind_static_method(const char *p_class, N p_method_name, M } template -MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info, const std::vector &p_default_args, bool p_return_nil_is_variant) { +MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info, const std::vector &p_default_args, bool p_return_nil_is_variant) { MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant); ERR_FAIL_COND_V(!bind, nullptr); bind->set_name(p_name); bind->set_default_arguments(p_default_args); - const char *instance_type = bind->get_instance_class(); + StringName instance_type = bind->get_instance_class(); - std::unordered_map::iterator type_it = classes.find(instance_type); + std::unordered_map::iterator type_it = classes.find(instance_type); if (type_it == classes.end()) { memdelete(bind); ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(instance_type)); diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index 155a7658..812409e9 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -48,8 +48,8 @@ namespace godot { class MethodBind { - const char *name = nullptr; - const char *instance_class = nullptr; + StringName name; + StringName instance_class; int argument_count = 0; uint32_t hint_flags = METHOD_FLAGS_DEFAULT; @@ -58,13 +58,13 @@ class MethodBind { bool _has_return = false; bool _vararg = false; - std::vector argument_names; + std::vector argument_names; GDNativeVariantType *argument_types = nullptr; std::vector default_arguments; protected: virtual GDNativeVariantType gen_argument_type(int p_arg) const = 0; - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const = 0; + virtual PropertyInfo gen_argument_type_info(int p_arg) const = 0; void generate_argument_types(int p_count); void set_const(bool p_const); void set_return(bool p_return); @@ -73,8 +73,8 @@ protected: void set_argument_count(int p_count); public: - const char *get_name() const; - void set_name(const char *p_name); + StringName get_name() const; + void set_name(const StringName &p_name); _FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); } _FORCE_INLINE_ const std::vector &get_default_arguments() const { return default_arguments; } _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { @@ -95,8 +95,8 @@ public: return default_arguments[idx]; } } - _FORCE_INLINE_ const char *get_instance_class() const { return instance_class; } - _FORCE_INLINE_ void set_instance_class(const char *p_class) { instance_class = p_class; } + _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } + _FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; } _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; _FORCE_INLINE_ bool is_const() const { return _is_const; } @@ -105,8 +105,8 @@ public: _FORCE_INLINE_ bool has_return() const { return _has_return; } _FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDNATIVE_EXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDNATIVE_EXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDNATIVE_EXTENSION_METHOD_FLAG_STATIC : 0); } _FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; } - void set_argument_names(const std::vector &p_names); - std::vector get_argument_names() const; + void set_argument_names(const std::vector &p_names); + std::vector get_argument_names() const; void set_default_arguments(const std::vector &p_default_arguments) { default_arguments = p_default_arguments; } _FORCE_INLINE_ GDNativeVariantType get_argument_type(int p_argument) const { @@ -114,17 +114,31 @@ public: return argument_types[p_argument + 1]; } - GDNativePropertyInfo get_argument_info(int p_argument) const; + PropertyInfo get_argument_info(int p_argument) const; virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0; + std::vector get_arguments_info_list() const { + std::vector vec; + // First element is return value + vec.reserve(argument_count + 1); + for (int i = 0; i < argument_count; i++) { + vec.push_back(get_argument_info(i - 1)); + } + return vec; + } + std::vector get_arguments_metadata_list() const { + std::vector vec; + // First element is return value + vec.reserve(argument_count + 1); + for (int i = 0; i < argument_count; i++) { + vec.push_back(get_argument_metadata(i - 1)); + } + return vec; + } + virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const = 0; virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const = 0; - // Extension info. - static GDNativeVariantType bind_get_argument_type(void *p_method_userdata, int32_t p_argument); - static void bind_get_argument_info(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info); - static GDNativeExtensionClassMethodArgumentMetadata bind_get_argument_metadata(void *p_method_userdata, int32_t p_argument); - static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return); @@ -136,16 +150,16 @@ class MethodBindVarArgBase : public MethodBind { protected: R(T::*method) (const Variant **, GDNativeInt, GDNativeCallError &); - std::vector arguments; + std::vector arguments; public: - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { + virtual PropertyInfo gen_argument_type_info(int p_arg) const { if (p_arg < 0) { return _gen_return_type_info(); } else if (p_arg < arguments.size()) { return arguments[p_arg]; } else { - return make_property_info(GDNATIVE_VARIANT_TYPE_NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); + return make_property_info(Variant::Type::NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); } } @@ -177,20 +191,13 @@ public: set_const(true); set_argument_count(p_method_info.arguments.size()); if (p_method_info.arguments.size()) { - std::vector names; + arguments = p_method_info.arguments; + + std::vector names; names.reserve(p_method_info.arguments.size()); for (int i = 0; i < p_method_info.arguments.size(); i++) { - names.push_back(p_method_info.arguments[i].name.utf8().get_data()); - arguments.push_back(GDNativePropertyInfo{ - static_cast(p_method_info.arguments[i].type), // GDNativeVariantType type; - _alloc_and_copy_cstr(p_method_info.arguments[i].name.utf8().get_data()), // const char *name; - _alloc_and_copy_cstr(p_method_info.arguments[i].class_name.utf8().get_data()), // const char *class_name; - p_method_info.arguments[i].hint, // NONE //uint32_t hint; - _alloc_and_copy_cstr(p_method_info.arguments[i].hint_string.utf8().get_data()), // const char *hint_string; - p_method_info.arguments[i].usage, // DEFAULT //uint32_t usage; - }); + names.push_back(p_method_info.arguments[i].name); } - set_argument_names(names); } @@ -198,16 +205,10 @@ public: set_return(should_returns); } - ~MethodBindVarArgBase() { - for (GDNativePropertyInfo &arg : arguments) { - memfree(const_cast(arg.name)); - memfree(const_cast(arg.class_name)); - memfree(const_cast(arg.hint_string)); - } - } + ~MethodBindVarArgBase() {} private: - GDNativePropertyInfo _gen_return_type_info() const { + PropertyInfo _gen_return_type_info() const { return reinterpret_cast(this)->_gen_return_type_info_impl(); } }; @@ -230,7 +231,7 @@ public: } private: - GDNativePropertyInfo _gen_return_type_info_impl() const { + PropertyInfo _gen_return_type_info_impl() const { return {}; } }; @@ -259,7 +260,7 @@ public: } private: - GDNativePropertyInfo _gen_return_type_info_impl() const { + PropertyInfo _gen_return_type_info_impl() const { return GetTypeInfo::get_class_info(); } }; @@ -302,12 +303,12 @@ protected: } } - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { - GDNativePropertyInfo pi; + virtual PropertyInfo gen_argument_type_info(int p_arg) const { + PropertyInfo pi; if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { call_get_argument_type_info(p_arg, pi); } else { - pi = GDNativePropertyInfo(); + pi = PropertyInfo(); } return pi; } @@ -378,12 +379,12 @@ protected: } } - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { - GDNativePropertyInfo pi; + virtual PropertyInfo gen_argument_type_info(int p_arg) const { + PropertyInfo pi; if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { call_get_argument_type_info(p_arg, pi); } else { - pi = GDNativePropertyInfo(); + pi = PropertyInfo(); } return pi; } @@ -455,9 +456,9 @@ protected: } } - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { + virtual PropertyInfo gen_argument_type_info(int p_arg) const { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { - GDNativePropertyInfo pi; + PropertyInfo pi; call_get_argument_type_info(p_arg, pi); return pi; } else { @@ -538,9 +539,9 @@ protected: } } - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { + virtual PropertyInfo gen_argument_type_info(int p_arg) const { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { - GDNativePropertyInfo pi; + PropertyInfo pi; call_get_argument_type_info(p_arg, pi); return pi; } else { @@ -618,12 +619,12 @@ protected: } } - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { - GDNativePropertyInfo pi; + virtual PropertyInfo gen_argument_type_info(int p_arg) const { + PropertyInfo pi; if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { call_get_argument_type_info(p_arg, pi); } else { - pi = GDNativePropertyInfo(); + pi = PropertyInfo(); } return pi; } @@ -683,9 +684,9 @@ protected: } } - virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const { + virtual PropertyInfo gen_argument_type_info(int p_arg) const { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { - GDNativePropertyInfo pi; + PropertyInfo pi; call_get_argument_type_info(p_arg, pi); return pi; } else { diff --git a/include/godot_cpp/core/object.hpp b/include/godot_cpp/core/object.hpp index 4ee413f7..e40f0860 100644 --- a/include/godot_cpp/core/object.hpp +++ b/include/godot_cpp/core/object.hpp @@ -53,7 +53,7 @@ namespace godot { struct MethodInfo { - const char *name; + StringName name; PropertyInfo return_val; uint32_t flags; int id = 0; @@ -68,33 +68,33 @@ struct MethodInfo { static MethodInfo from_dict(const Dictionary &p_dict); MethodInfo(); - MethodInfo(const char *p_name); + MethodInfo(StringName p_name); template - MethodInfo(const char *p_name, const Args &...args); + MethodInfo(StringName p_name, const Args &...args); MethodInfo(Variant::Type ret); - MethodInfo(Variant::Type ret, const char *p_name); + MethodInfo(Variant::Type ret, StringName p_name); template - MethodInfo(Variant::Type ret, const char *p_name, const Args &...args); - MethodInfo(const PropertyInfo &p_ret, const char *p_name); + MethodInfo(Variant::Type ret, StringName p_name, const Args &...args); + MethodInfo(const PropertyInfo &p_ret, StringName p_name); template - MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...); + MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...); }; template -MethodInfo::MethodInfo(const char *p_name, const Args &...args) : +MethodInfo::MethodInfo(StringName p_name, const Args &...args) : name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) { arguments = { args... }; } template -MethodInfo::MethodInfo(Variant::Type ret, const char *p_name, const Args &...args) : +MethodInfo::MethodInfo(Variant::Type ret, StringName p_name, const Args &...args) : name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) { return_val.type = ret; arguments = { args... }; } template -MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...args) : +MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...args) : name(p_name), return_val(p_ret), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) { arguments = { args... }; } @@ -137,7 +137,8 @@ T *Object::cast_to(Object *p_object) { if (p_object == nullptr) { return nullptr; } - GDNativeObjectPtr casted = internal::gdn_interface->object_cast_to(p_object->_owner, internal::gdn_interface->classdb_get_class_tag(T::get_class_static())); + StringName class_name = T::get_class_static(); + GDNativeObjectPtr casted = internal::gdn_interface->object_cast_to(p_object->_owner, internal::gdn_interface->classdb_get_class_tag(class_name._native_ptr())); if (casted == nullptr) { return nullptr; } @@ -149,7 +150,8 @@ const T *Object::cast_to(const Object *p_object) { if (p_object == nullptr) { return nullptr; } - GDNativeObjectPtr casted = internal::gdn_interface->object_cast_to(p_object->_owner, internal::gdn_interface->classdb_get_class_tag(T::get_class_static())); + StringName class_name = T::get_class_static(); + GDNativeObjectPtr casted = internal::gdn_interface->object_cast_to(p_object->_owner, internal::gdn_interface->classdb_get_class_tag(class_name._native_ptr())); if (casted == nullptr) { return nullptr; } diff --git a/include/godot_cpp/core/property_info.hpp b/include/godot_cpp/core/property_info.hpp index 3f9084b7..71343e9d 100644 --- a/include/godot_cpp/core/property_info.hpp +++ b/include/godot_cpp/core/property_info.hpp @@ -45,15 +45,15 @@ namespace godot { struct PropertyInfo { Variant::Type type = Variant::NIL; - String name; - String class_name; + StringName name; + StringName class_name; uint32_t hint = 0; String hint_string; uint32_t usage = 7; PropertyInfo() = default; - PropertyInfo(Variant::Type p_type, const String &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const String &p_class_name = "") : + PropertyInfo(Variant::Type p_type, const StringName &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") : type(p_type), name(p_name), hint(p_hint), @@ -66,7 +66,7 @@ struct PropertyInfo { } } - PropertyInfo(GDNativeVariantType p_type, const String &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const String &p_class_name = "") : + PropertyInfo(GDNativeVariantType p_type, const StringName &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") : PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {} }; diff --git a/include/godot_cpp/core/type_info.hpp b/include/godot_cpp/core/type_info.hpp index 0610eca1..a2abe44d 100644 --- a/include/godot_cpp/core/type_info.hpp +++ b/include/godot_cpp/core/type_info.hpp @@ -69,8 +69,8 @@ struct TypeInherits { !TypesAreSame::value; }; -static GDNativePropertyInfo make_property_info(GDNativeVariantType p_type, const char *p_name, uint32_t p_hint = PROPERTY_HINT_NONE, const char *p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const char *p_class_name = "") { - GDNativePropertyInfo info; +static PropertyInfo make_property_info(Variant::Type p_type, const StringName &p_name, uint32_t p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") { + PropertyInfo info; info.type = p_type; info.name = p_name; info.hint = p_hint; @@ -98,16 +98,16 @@ struct GetTypeInfo; struct GetTypeInfo { \ static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \ static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(VARIANT_TYPE, ""); \ + static inline PropertyInfo get_class_info() { \ + return make_property_info((Variant::Type)VARIANT_TYPE, ""); \ } \ }; \ template <> \ struct GetTypeInfo { \ static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \ static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(VARIANT_TYPE, ""); \ + static inline PropertyInfo get_class_info() { \ + return make_property_info((Variant::Type)VARIANT_TYPE, ""); \ } \ }; @@ -116,16 +116,16 @@ struct GetTypeInfo; struct GetTypeInfo { \ static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \ static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = m_metadata; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(VARIANT_TYPE, ""); \ + static inline PropertyInfo get_class_info() { \ + return make_property_info((Variant::Type)VARIANT_TYPE, ""); \ } \ }; \ template <> \ struct GetTypeInfo { \ static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type; \ static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = m_metadata; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(VARIANT_TYPE, ""); \ + static inline PropertyInfo get_class_info() { \ + return make_property_info((Variant::Type)VARIANT_TYPE, ""); \ } \ }; @@ -182,8 +182,8 @@ template <> struct GetTypeInfo { static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_NIL; static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); } }; @@ -191,8 +191,8 @@ template <> struct GetTypeInfo { static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_NIL; static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); } }; @@ -200,8 +200,8 @@ template struct GetTypeInfo::value>::type> { static const GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_OBJECT; static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_OBJECT, T::get_class_static()); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::OBJECT, T::get_class_static()); } }; @@ -209,19 +209,19 @@ template struct GetTypeInfo::value>::type> { static const GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_OBJECT; static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_OBJECT, T::get_class_static()); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::OBJECT, T::get_class_static()); } }; -#define TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_impl) \ - template <> \ - struct GetTypeInfo { \ - static const Variant::Type VARIANT_TYPE = Variant::INT; \ - static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(GDNATIVE_VARIANT_TYPE_INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, #m_class "." #m_enum); \ - } \ +#define TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_impl) \ + template <> \ + struct GetTypeInfo { \ + static const Variant::Type VARIANT_TYPE = Variant::INT; \ + static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ + static inline PropertyInfo get_class_info() { \ + return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, #m_class "." #m_enum); \ + } \ }; #define MAKE_ENUM_TYPE_INFO(m_class, m_enum) \ @@ -231,7 +231,7 @@ struct GetTypeInfo::value>: TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, const m_class::m_enum &) template -inline const char *__constant_get_enum_name(T param, const char *p_constant) { +inline StringName __constant_get_enum_name(T param, StringName p_constant) { if (GetTypeInfo::VARIANT_TYPE == Variant::NIL) { ERR_PRINT(("Missing VARIANT_ENUM_CAST for constant's enum: " + String(p_constant)).utf8().get_data()); } @@ -251,24 +251,24 @@ public: _FORCE_INLINE_ operator Variant() const { return value; } }; -#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, m_impl) \ - template <> \ - struct GetTypeInfo { \ - static const Variant::Type VARIANT_TYPE = Variant::INT; \ - static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(GDNATIVE_VARIANT_TYPE_INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \ - #m_class "." #m_enum); \ - } \ - }; \ - template <> \ - struct GetTypeInfo> { \ - static const Variant::Type VARIANT_TYPE = Variant::INT; \ - static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(GDNATIVE_VARIANT_TYPE_INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \ - #m_class "." #m_enum); \ - } \ +#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, m_impl) \ + template <> \ + struct GetTypeInfo { \ + static const Variant::Type VARIANT_TYPE = Variant::INT; \ + static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ + static inline PropertyInfo get_class_info() { \ + return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \ + #m_class "." #m_enum); \ + } \ + }; \ + template <> \ + struct GetTypeInfo> { \ + static const Variant::Type VARIANT_TYPE = Variant::INT; \ + static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ + static inline PropertyInfo get_class_info() { \ + return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \ + #m_class "." #m_enum); \ + } \ }; #define MAKE_BITFIELD_TYPE_INFO(m_class, m_enum) \ @@ -309,8 +309,8 @@ template struct GetTypeInfo> { static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, T::get_class_static()); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, T::get_class_static()); } }; @@ -318,27 +318,27 @@ template struct GetTypeInfo &> { static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; - static inline GDNativePropertyInfo get_class_info() { - return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, T::get_class_static()); + static inline PropertyInfo get_class_info() { + return make_property_info(Variant::Type::ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, T::get_class_static()); } }; -#define MAKE_TYPED_ARRAY_INFO(m_type, m_variant_type) \ - template <> \ - struct GetTypeInfo> { \ - static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; \ - static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type).utf8().get_data()); \ - } \ - }; \ - template <> \ - struct GetTypeInfo &> { \ - static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; \ - static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ - static inline GDNativePropertyInfo get_class_info() { \ - return make_property_info(GDNATIVE_VARIANT_TYPE_ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type).utf8().get_data()); \ - } \ +#define MAKE_TYPED_ARRAY_INFO(m_type, m_variant_type) \ + template <> \ + struct GetTypeInfo> { \ + static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; \ + static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ + static inline PropertyInfo get_class_info() { \ + return make_property_info(Variant::Type::ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type).utf8().get_data()); \ + } \ + }; \ + template <> \ + struct GetTypeInfo &> { \ + static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_ARRAY; \ + static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ + static inline PropertyInfo get_class_info() { \ + return make_property_info(Variant::Type::ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type).utf8().get_data()); \ + } \ }; MAKE_TYPED_ARRAY_INFO(bool, Variant::BOOL) diff --git a/src/classes/wrapped.cpp b/src/classes/wrapped.cpp index 84ac3a47..fead0501 100644 --- a/src/classes/wrapped.cpp +++ b/src/classes/wrapped.cpp @@ -36,20 +36,24 @@ namespace godot { -const StringName *Wrapped::_get_extension_class() const { +const StringName *Wrapped::_get_extension_class_name() const { return nullptr; } void Wrapped::_postinitialize() { - const StringName *extension_class = _get_extension_class(); + const StringName *extension_class = _get_extension_class_name(); if (extension_class) { - godot::internal::gdn_interface->object_set_instance(_owner, (void *)extension_class, this); + // TODO: replace C cast by a proper reinterpret_cast once `object_set_instance` signature correctly handles `const GDNativeStringNamePtr` param + // (see: https://github.com/godotengine/godot/pull/67751) + godot::internal::gdn_interface->object_set_instance(_owner, (GDNativeStringNamePtr)(extension_class), this); } godot::internal::gdn_interface->object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks()); } Wrapped::Wrapped(const StringName p_godot_class) { - _owner = godot::internal::gdn_interface->classdb_construct_object((void *)&p_godot_class); + // TODO: replace C cast by a proper reinterpret_cast once `classdb_construct_object` signature correctly handles `const GDNativeStringNamePtr` param + // (see: https://github.com/godotengine/godot/pull/67751) + _owner = godot::internal::gdn_interface->classdb_construct_object((GDNativeStringNamePtr)(p_godot_class._native_ptr())); } Wrapped::Wrapped(GodotObject *p_godot_object) { diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index 8f1c522c..49cc9bd1 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -39,40 +39,40 @@ namespace godot { -std::unordered_map ClassDB::classes; +std::unordered_map ClassDB::classes; GDNativeInitializationLevel ClassDB::current_level = GDNATIVE_INITIALIZATION_CORE; -MethodDefinition D_METHOD(const char *p_name) { +MethodDefinition D_METHOD(StringName p_name) { return MethodDefinition(p_name); } -MethodDefinition D_METHOD(const char *p_name, const char *p_arg1) { +MethodDefinition D_METHOD(StringName p_name, StringName p_arg1) { MethodDefinition method(p_name); method.args.push_front(p_arg1); return method; } -void ClassDB::add_property_group(const char *p_class, const char *p_name, const char *p_prefix) { +void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix) { ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}{1}' to non-existing class '{2}'.").format(Array::make(p_prefix, p_name, p_class))); - internal::gdn_interface->classdb_register_extension_class_property_group(internal::library, p_class, p_name, p_prefix); + internal::gdn_interface->classdb_register_extension_class_property_group(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr()); } -void ClassDB::add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix) { +void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix) { ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}{1}' to non-existing class '{2}'.").format(Array::make(p_prefix, p_name, p_class))); - internal::gdn_interface->classdb_register_extension_class_property_subgroup(internal::library, p_class, p_name, p_prefix); + internal::gdn_interface->classdb_register_extension_class_property_subgroup(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr()); } -void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index) { +void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) { ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}' to non-existing class '{1}'.").format(Array::make(p_pinfo.name, p_class))); ClassInfo &info = classes[p_class]; - ERR_FAIL_COND_MSG(info.property_names.find(p_pinfo.name.utf8().get_data()) != info.property_names.end(), String("Property '{0}' already exists in class '{1}'.").format(Array::make(p_pinfo.name, p_class))); + ERR_FAIL_COND_MSG(info.property_names.find(p_pinfo.name) != info.property_names.end(), String("Property '{0}' already exists in class '{1}'.").format(Array::make(p_pinfo.name, p_class))); MethodBind *setter = nullptr; - if (p_setter) { + if (p_setter != String("")) { setter = get_method(p_class, p_setter); ERR_FAIL_COND_MSG(!setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name))); @@ -81,7 +81,7 @@ void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, con ERR_FAIL_COND_MSG(exp_args != setter->get_argument_count(), String("Setter method '{0}::{1}()' must take a single argument.").format(Array::make(p_class, p_setter))); } - ERR_FAIL_COND_MSG(!p_getter, String("Getter method must be specified for '{0}::{1}'.").format(Array::make(p_class, p_pinfo.name))); + ERR_FAIL_COND_MSG(p_getter == String(""), String("Getter method must be specified for '{0}::{1}'.").format(Array::make(p_class, p_pinfo.name))); MethodBind *getter = get_method(p_class, p_getter); ERR_FAIL_COND_MSG(!getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name))); @@ -91,15 +91,15 @@ void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, con } // register property with plugin - info.property_names.insert(p_pinfo.name.utf8().get_data()); + info.property_names.insert(p_pinfo.name); // register with Godot GDNativePropertyInfo prop_info = { static_cast(p_pinfo.type), // GDNativeVariantType type; - _alloc_and_copy_cstr(p_pinfo.name.utf8().get_data()), // const char *name; - _alloc_and_copy_cstr(p_pinfo.class_name.utf8().get_data()), // const char *class_name; + p_pinfo.name._native_ptr(), // GDNativeStringNamePtr name; + p_pinfo.class_name._native_ptr(), // GDNativeStringNamePtr class_name; p_pinfo.hint, // NONE //uint32_t hint; - _alloc_and_copy_cstr(p_pinfo.hint_string.utf8().get_data()), // const char *hint_string; + p_pinfo.hint_string._native_ptr(), // GDNativeStringPtr hint_string; p_pinfo.usage, // DEFAULT //uint32_t usage; }; @@ -111,19 +111,15 @@ void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, con setget.index = p_index; setget.type = p_pinfo.type; - internal::gdn_interface->classdb_register_extension_class_property(internal::library, info.name, &prop_info, setget.setter, setget.getter); - - memfree(const_cast(prop_info.name)); - memfree(const_cast(prop_info.class_name)); - memfree(const_cast(prop_info.hint_string)); + internal::gdn_interface->classdb_register_extension_class_property(internal::library, info.name._native_ptr(), &prop_info, setget.setter._native_ptr(), setget.getter._native_ptr()); } -MethodBind *ClassDB::get_method(const char *p_class, const char *p_method) { +MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_method) { ERR_FAIL_COND_V_MSG(classes.find(p_class) == classes.end(), nullptr, String("Class '{0}' not found.").format(p_class)); ClassInfo *type = &classes[p_class]; while (type) { - std::unordered_map::iterator method = type->method_map.find(p_method); + std::unordered_map::iterator method = type->method_map.find(p_method); if (method != type->method_map.end()) { return method->second; } @@ -135,9 +131,9 @@ MethodBind *ClassDB::get_method(const char *p_class, const char *p_method) { } MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount) { - const char *instance_type = p_bind->get_instance_class(); + StringName instance_type = p_bind->get_instance_class(); - std::unordered_map::iterator type_it = classes.find(instance_type); + std::unordered_map::iterator type_it = classes.find(instance_type); if (type_it == classes.end()) { memdelete(p_bind); ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(instance_type)); @@ -164,10 +160,10 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const M p_bind->set_hint_flags(p_flags); - std::vector args; + std::vector args; args.resize(method_name.args.size()); size_t arg_index = 0; - for (std::string arg : method_name.args) { + for (StringName arg : method_name.args) { args[arg_index++] = arg; } @@ -192,34 +188,57 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const M return p_bind; } -void ClassDB::bind_method_godot(const char *p_class_name, MethodBind *p_method) { +void ClassDB::bind_method_godot(const StringName &p_class_name, MethodBind *p_method) { std::vector def_args; const std::vector &def_args_val = p_method->get_default_arguments(); - def_args.resize(def_args_val.size()); for (int i = 0; i < def_args_val.size(); i++) { def_args[i] = (GDNativeVariantPtr)&def_args_val[i]; } + std::vector return_value_and_arguments_info = p_method->get_arguments_info_list(); + std::vector return_value_and_arguments_metadata = p_method->get_arguments_metadata_list(); + + std::vector return_value_and_arguments_gdnative_info; + return_value_and_arguments_gdnative_info.reserve(return_value_and_arguments_info.size()); + for (std::vector::iterator it = return_value_and_arguments_info.begin(); it != return_value_and_arguments_info.end(); it++) { + return_value_and_arguments_gdnative_info.push_back( + GDNativePropertyInfo{ + static_cast(it->type), // GDNativeVariantType type; + it->name._native_ptr(), // GDNativeStringNamePtr name; + it->class_name._native_ptr(), // GDNativeStringNamePtr class_name; + it->hint, // uint32_t hint; + it->hint_string._native_ptr(), // GDNativeStringPtr hint_string; + it->usage, // uint32_t usage; + }); + } + + GDNativePropertyInfo *return_value_info = return_value_and_arguments_gdnative_info.data(); + GDNativeExtensionClassMethodArgumentMetadata *return_value_metadata = return_value_and_arguments_metadata.data(); + GDNativePropertyInfo *arguments_info = return_value_and_arguments_gdnative_info.data() + 1; + GDNativeExtensionClassMethodArgumentMetadata *arguments_metadata = return_value_and_arguments_metadata.data() + 1; + + StringName name = p_method->get_name(); GDNativeExtensionClassMethodInfo method_info = { - p_method->get_name(), // const char *name; + name._native_ptr(), // const GDNativeStringNamePtr; p_method, // void *method_userdata; MethodBind::bind_call, // GDNativeExtensionClassMethodCall call_func; MethodBind::bind_ptrcall, // GDNativeExtensionClassMethodPtrCall ptrcall_func; p_method->get_hint_flags(), // uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */ (uint32_t)p_method->get_argument_count(), // uint32_t argument_count; (GDNativeBool)p_method->has_return(), // GDNativeBool has_return_value; - MethodBind::bind_get_argument_type, //(GDNativeExtensionClassMethodGetArgumentType) get_argument_type_func; - MethodBind::bind_get_argument_info, // GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ - MethodBind::bind_get_argument_metadata, // GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func; + return_value_info, // GDNativePropertyInfo * + *return_value_metadata, // GDNativeExtensionClassMethodArgumentMetadata * + arguments_info, // GDNativePropertyInfo * + arguments_metadata, // GDNativeExtensionClassMethodArgumentMetadata * (uint32_t)p_method->get_default_argument_count(), // uint32_t default_argument_count; def_args.data(), // GDNativeVariantPtr *default_arguments; }; - internal::gdn_interface->classdb_register_extension_class_method(internal::library, p_class_name, &method_info); + internal::gdn_interface->classdb_register_extension_class_method(internal::library, p_class_name._native_ptr(), &method_info); } -void ClassDB::add_signal(const char *p_class, const MethodInfo &p_signal) { - std::unordered_map::iterator type_it = classes.find(p_class); +void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) { + std::unordered_map::iterator type_it = classes.find(p_class); ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(p_class)); @@ -242,25 +261,19 @@ void ClassDB::add_signal(const char *p_class, const MethodInfo &p_signal) { for (const PropertyInfo &par : p_signal.arguments) { parameters.push_back(GDNativePropertyInfo{ static_cast(par.type), // GDNativeVariantType type; - _alloc_and_copy_cstr(par.name.utf8().get_data()), // const char *name; - _alloc_and_copy_cstr(par.class_name.utf8().get_data()), // const char *class_name; + par.name._native_ptr(), // const GDNativeStringNamePtr name; + par.class_name._native_ptr(), // const GDNativeStringNamePtr class_name; par.hint, // NONE //uint32_t hint; - _alloc_and_copy_cstr(par.hint_string.utf8().get_data()), // const char *hint_string; + par.hint_string._native_ptr(), // const GDNativeStringPtr hint_string; par.usage, // DEFAULT //uint32_t usage; }); } - internal::gdn_interface->classdb_register_extension_class_signal(internal::library, cl.name, p_signal.name, parameters.data(), parameters.size()); - - for (GDNativePropertyInfo &par : parameters) { - memfree(const_cast(par.name)); - memfree(const_cast(par.class_name)); - memfree(const_cast(par.hint_string)); - } + internal::gdn_interface->classdb_register_extension_class_signal(internal::library, cl.name._native_ptr(), p_signal.name._native_ptr(), parameters.data(), parameters.size()); } -void ClassDB::bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield) { - std::unordered_map::iterator type_it = classes.find(p_class_name); +void ClassDB::bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield) { + std::unordered_map::iterator type_it = classes.find(p_class_name); ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(p_class_name)); @@ -273,24 +286,23 @@ void ClassDB::bind_integer_constant(const char *p_class_name, const char *p_enum type.constant_names.insert(p_constant_name); // Register it with Godot - internal::gdn_interface->classdb_register_extension_class_integer_constant(internal::library, p_class_name, p_enum_name, p_constant_name, p_constant_value, p_is_bitfield); + internal::gdn_interface->classdb_register_extension_class_integer_constant(internal::library, p_class_name._native_ptr(), p_enum_name._native_ptr(), p_constant_name._native_ptr(), p_constant_value, p_is_bitfield); } - -GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, const char *p_name) { +GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, const GDNativeStringNamePtr p_name) { // This is called by Godot the first time it calls a virtual function, and it caches the result, per object instance. // Because of this, it can happen from different threads at once. // It should be ok not using any mutex as long as we only READ data. + const StringName *class_name = reinterpret_cast(p_userdata); + const StringName *name = reinterpret_cast(p_name); - const char *class_name = (const char *)p_userdata; - - std::unordered_map::iterator type_it = classes.find(class_name); - ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, String("Class '{0}' doesn't exist.").format(class_name)); + std::unordered_map::iterator type_it = classes.find(*class_name); + ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, String("Class '{0}' doesn't exist.").format(*class_name)); const ClassInfo *type = &type_it->second; // Find method in current class, or any of its parent classes (Godot classes not included) while (type != nullptr) { - std::unordered_map::const_iterator method_it = type->virtual_methods.find(p_name); + std::unordered_map::const_iterator method_it = type->virtual_methods.find(*name); if (method_it != type->virtual_methods.end()) { return method_it->second; @@ -302,8 +314,8 @@ GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, co return nullptr; } -void ClassDB::bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call) { - std::unordered_map::iterator type_it = classes.find(p_class); +void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p_method, GDNativeExtensionClassCallVirtual p_call) { + std::unordered_map::iterator type_it = classes.find(p_class); ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(p_class)); ClassInfo &type = type_it->second; @@ -318,7 +330,7 @@ void ClassDB::initialize_class(const ClassInfo &p_cl) { } void ClassDB::initialize(GDNativeInitializationLevel p_level) { - for (const std::pair pair : classes) { + for (const std::pair pair : classes) { const ClassInfo &cl = pair.second; if (cl.level != p_level) { continue; @@ -329,13 +341,13 @@ void ClassDB::initialize(GDNativeInitializationLevel p_level) { } void ClassDB::deinitialize(GDNativeInitializationLevel p_level) { - for (const std::pair pair : classes) { + for (const std::pair pair : classes) { const ClassInfo &cl = pair.second; if (cl.level != p_level) { continue; } - internal::gdn_interface->classdb_unregister_extension_class(internal::library, cl.name); + internal::gdn_interface->classdb_unregister_extension_class(internal::library, cl.name._native_ptr()); for (auto method : cl.method_map) { memdelete(method.second); diff --git a/src/core/method_bind.cpp b/src/core/method_bind.cpp index 563ea7f0..9c0ce4b3 100644 --- a/src/core/method_bind.cpp +++ b/src/core/method_bind.cpp @@ -32,11 +32,11 @@ namespace godot { -const char *MethodBind::get_name() const { +StringName MethodBind::get_name() const { return name; } -void MethodBind::set_name(const char *p_name) { +void MethodBind::set_name(const StringName &p_name) { name = p_name; } @@ -60,11 +60,11 @@ void MethodBind::set_vararg(bool p_vararg) { _vararg = p_vararg; } -void MethodBind::set_argument_names(const std::vector &p_names) { +void MethodBind::set_argument_names(const std::vector &p_names) { argument_names = p_names; } -std::vector MethodBind::get_argument_names() const { +std::vector MethodBind::get_argument_names() const { return argument_names; } @@ -83,29 +83,14 @@ void MethodBind::generate_argument_types(int p_count) { } } -GDNativePropertyInfo MethodBind::get_argument_info(int p_argument) const { - GDNativePropertyInfo info = gen_argument_type_info(p_argument); +PropertyInfo MethodBind::get_argument_info(int p_argument) const { + PropertyInfo info = gen_argument_type_info(p_argument); if (p_argument >= 0) { - info.name = p_argument < (int)argument_names.size() ? argument_names[p_argument].c_str() : ""; + info.name = p_argument < (int)argument_names.size() ? argument_names[p_argument] : ""; } return info; } -GDNativeVariantType MethodBind::bind_get_argument_type(void *p_method_userdata, int32_t p_argument) { - const MethodBind *bind = reinterpret_cast(p_method_userdata); - return bind->get_argument_type(p_argument); -} - -void MethodBind::bind_get_argument_info(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info) { - const MethodBind *bind = reinterpret_cast(p_method_userdata); - *r_info = bind->get_argument_info(p_argument); -} - -GDNativeExtensionClassMethodArgumentMetadata MethodBind::bind_get_argument_metadata(void *p_method_userdata, int32_t p_argument) { - const MethodBind *bind = reinterpret_cast(p_method_userdata); - return bind->get_argument_metadata(p_argument); -} - void MethodBind::bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { const MethodBind *bind = reinterpret_cast(p_method_userdata); Variant ret = bind->call(p_instance, p_args, p_argument_count, *r_error); diff --git a/src/core/object.cpp b/src/core/object.cpp index e1feabb8..b0025eaf 100644 --- a/src/core/object.cpp +++ b/src/core/object.cpp @@ -35,7 +35,7 @@ namespace godot { MethodInfo::MethodInfo() : flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {} -MethodInfo::MethodInfo(const char *p_name) : +MethodInfo::MethodInfo(StringName p_name) : name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {} MethodInfo::MethodInfo(Variant::Type ret) : @@ -43,12 +43,12 @@ MethodInfo::MethodInfo(Variant::Type ret) : return_val.type = ret; } -MethodInfo::MethodInfo(Variant::Type ret, const char *p_name) : +MethodInfo::MethodInfo(Variant::Type ret, StringName p_name) : name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) { return_val.type = ret; } -MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name) : +MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name) : name(p_name), return_val(p_ret), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {} } // namespace godot From a706a9ceb91116aa20895df3b422c164378dc353 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Sun, 23 Oct 2022 14:38:29 +0200 Subject: [PATCH 3/7] Remove now useless `_alloc_and_copy_cstr` --- include/godot_cpp/classes/wrapped.hpp | 7 ------- include/godot_cpp/core/class_db.hpp | 7 ------- include/godot_cpp/core/method_bind.hpp | 7 ------- 3 files changed, 21 deletions(-) diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 83c4cc30..58da7712 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -87,13 +87,6 @@ public: return 0; } - static _FORCE_INLINE_ char *_alloc_and_copy_cstr(const char *p_str) { - size_t size = strlen(p_str) + 1; - char *ret = reinterpret_cast(memalloc(size)); - memcpy(ret, p_str, size); - return ret; - } - // Must be public but you should not touch this. GodotObject *_owner = nullptr; }; diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index f6fbd39f..0353621e 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -109,13 +109,6 @@ private: static void initialize_class(const ClassInfo &cl); static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method); - static _FORCE_INLINE_ char *_alloc_and_copy_cstr(const char *p_str) { - size_t size = strlen(p_str) + 1; - char *ret = reinterpret_cast(memalloc(size)); - memcpy(ret, p_str, size); - return ret; - } - template static void _register_class(bool p_virtual = false); diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index 812409e9..c80c0408 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -175,13 +175,6 @@ public: ERR_FAIL(); // Can't call. } - static _FORCE_INLINE_ char *_alloc_and_copy_cstr(const char *p_str) { - size_t size = strlen(p_str) + 1; - char *ret = reinterpret_cast(memalloc(size)); - memcpy(ret, p_str, size); - return ret; - } - MethodBindVarArgBase( R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_method_info, From d1963dc133d3fdc8f6ab90d47a87158dac7ebd2a Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Sun, 23 Oct 2022 14:39:16 +0200 Subject: [PATCH 4/7] Correct __constant_get_bitfield_name with StringName --- include/godot_cpp/core/type_info.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/godot_cpp/core/type_info.hpp b/include/godot_cpp/core/type_info.hpp index a2abe44d..4c3f1bf7 100644 --- a/include/godot_cpp/core/type_info.hpp +++ b/include/godot_cpp/core/type_info.hpp @@ -278,7 +278,7 @@ public: TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, const m_enum &) template -inline const char *__constant_get_bitfield_name(T param, const char *p_constant) { +inline StringName __constant_get_bitfield_name(T param, StringName p_constant) { if (GetTypeInfo::VARIANT_TYPE == Variant::NIL) { ERR_PRINT(("Missing VARIANT_ENUM_CAST for constant's bitfield: " + String(p_constant)).utf8().get_data()); } From 3b82d5937bd1b4d44cc38cbdbc59ee37a89f07fd Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Sun, 23 Oct 2022 14:45:57 +0200 Subject: [PATCH 5/7] Correct GDNativeExtensionScriptInstanceToString --- godot-headers/godot/gdnative_interface.h | 4 ++-- include/godot_cpp/classes/wrapped.hpp | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/godot-headers/godot/gdnative_interface.h b/godot-headers/godot/gdnative_interface.h index d99d6a92..68eed5a1 100644 --- a/godot-headers/godot/gdnative_interface.h +++ b/godot-headers/godot/gdnative_interface.h @@ -225,7 +225,7 @@ typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstanceP typedef GDNativeBool (*GDNativeExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name); typedef GDNativeBool (*GDNativeExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); -typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr p_out); +typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr p_out); typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); @@ -324,7 +324,7 @@ typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensi typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what); -typedef const char *(*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid); +typedef void (*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr r_out); typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 58da7712..5208e4e6 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -67,7 +67,7 @@ protected: static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list) {} static GDNativeBool property_can_revert_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name) { return false; } static GDNativeBool property_get_revert_bind(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret) { return false; } - static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr r_out) {} + static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr r_out) {} GDNativePropertyInfo *plist = nullptr; uint32_t plist_size = 0; @@ -264,14 +264,15 @@ public: return false; \ } \ \ - static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr r_out) { \ + static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr r_out) { \ if (p_instance && m_class::_get_to_string()) { \ if (m_class::_get_to_string() != m_inherits::_get_to_string()) { \ m_class *cls = reinterpret_cast(p_instance); \ *reinterpret_cast<::godot::String *>(r_out) = cls->_to_string(); \ + *r_is_valid = true; \ return; \ } \ - m_inherits::to_string_bind(p_instance, r_out); \ + m_inherits::to_string_bind(p_instance, r_is_valid, r_out); \ } \ } \ \ From b6ba0dca13c1cda5826f23abf203c2f05c0bee42 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Sun, 23 Oct 2022 22:31:57 +0200 Subject: [PATCH 6/7] StringName is working fine with demo \o/ --- binding_generator.py | 16 ++++++++++++++-- include/godot_cpp/classes/wrapped.hpp | 10 +++++----- include/godot_cpp/core/class_db.hpp | 4 ++-- include/godot_cpp/core/method_bind.hpp | 2 +- src/core/class_db.cpp | 12 ++++++------ src/variant/variant.cpp | 2 +- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 33bd568e..380033d7 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -397,6 +397,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("\tfriend class Variant;") + if class_name == "String": + result.append("\tfriend class StringName;") result.append("") result.append("\tstatic struct _MethodBindings {") @@ -439,6 +441,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("\tstatic void init_bindings();") + result.append("\tstatic void _init_bindings_constructors_destructor();") result.append("") result.append("public:") @@ -675,7 +678,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append(f"{class_name}::_MethodBindings {class_name}::_method_bindings;") result.append("") - result.append(f"void {class_name}::init_bindings() {{") + result.append(f"void {class_name}::_init_bindings_constructors_destructor() {{") if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: @@ -688,7 +691,16 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl f"\t_method_bindings.destructor = internal::gdn_interface->variant_get_ptr_destructor({enum_type_name});" ) - result.append(f"StringName __name;") + result.append("}") + + result.append(f"void {class_name}::init_bindings() {{") + + # StringName's constructor internally uses String, so it constructor must be ready ! + if class_name == "StringName": + result.append(f"\tString::_init_bindings_constructors_destructor();") + result.append(f"\t{class_name}::_init_bindings_constructors_destructor();") + + result.append(f"\tStringName __name;") if "methods" in builtin_api: for method in builtin_api["methods"]: diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 5208e4e6..1dfa5a24 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -78,7 +78,7 @@ protected: Wrapped(GodotObject *p_godot_object); public: - static StringName get_class_static() { + static StringName &get_class_static() { static StringName string_name = StringName("Wrapped"); return string_name; } @@ -159,12 +159,12 @@ public: initialized = true; \ } \ \ - static StringName get_class_static() { \ + static StringName &get_class_static() { \ static StringName string_name = StringName(#m_class); \ return string_name; \ } \ \ - static StringName get_parent_class_static() { \ + static StringName &get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ \ @@ -349,12 +349,12 @@ protected: public: \ static void initialize_class() {} \ \ - static StringName get_class_static() { \ + static StringName &get_class_static() { \ static StringName string_name = StringName(#m_class); \ return string_name; \ } \ \ - static StringName get_parent_class_static() { \ + static StringName &get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ \ diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 0353621e..634e55c2 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -191,7 +191,7 @@ void ClassDB::_register_class(bool p_virtual) { T::free, // GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ &ClassDB::get_virtual_func, // GDNativeExtensionClassGetVirtual get_virtual_func; nullptr, // GDNativeExtensionClassGetRID get_rid; - (void *)&cl.name, // void *class_userdata; + (void *)&T::get_class_static(), // void *class_userdata; }; internal::gdn_interface->classdb_register_extension_class(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info); @@ -249,7 +249,7 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p std::unordered_map::iterator type_it = classes.find(instance_type); if (type_it == classes.end()) { memdelete(bind); - ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(instance_type)); + ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(Array::make(instance_type))); } ClassInfo &type = type_it->second; diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index c80c0408..d7d747d8 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -121,7 +121,7 @@ public: std::vector vec; // First element is return value vec.reserve(argument_count + 1); - for (int i = 0; i < argument_count; i++) { + for (int i = 0; i < argument_count + 1; i++) { vec.push_back(get_argument_info(i - 1)); } return vec; diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index 49cc9bd1..97112b70 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -115,7 +115,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf } MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_method) { - ERR_FAIL_COND_V_MSG(classes.find(p_class) == classes.end(), nullptr, String("Class '{0}' not found.").format(p_class)); + ERR_FAIL_COND_V_MSG(classes.find(p_class) == classes.end(), nullptr, String("Class '{0}' not found.").format(Array::make(p_class))); ClassInfo *type = &classes[p_class]; while (type) { @@ -136,7 +136,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const M std::unordered_map::iterator type_it = classes.find(instance_type); if (type_it == classes.end()) { memdelete(p_bind); - ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(instance_type)); + ERR_FAIL_V_MSG(nullptr, String("Class '{0}' doesn't exist.").format(Array::make(instance_type))); } ClassInfo &type = type_it->second; @@ -240,7 +240,7 @@ void ClassDB::bind_method_godot(const StringName &p_class_name, MethodBind *p_me void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) { std::unordered_map::iterator type_it = classes.find(p_class); - ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(p_class)); + ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class))); ClassInfo &cl = type_it->second; @@ -275,7 +275,7 @@ void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) void ClassDB::bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield) { std::unordered_map::iterator type_it = classes.find(p_class_name); - ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(p_class_name)); + ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class_name))); ClassInfo &type = type_it->second; @@ -296,7 +296,7 @@ GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, co const StringName *name = reinterpret_cast(p_name); std::unordered_map::iterator type_it = classes.find(*class_name); - ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, String("Class '{0}' doesn't exist.").format(*class_name)); + ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, String("Class '{0}' doesn't exist.").format(Array::make(*class_name))); const ClassInfo *type = &type_it->second; @@ -316,7 +316,7 @@ GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, co void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p_method, GDNativeExtensionClassCallVirtual p_call) { std::unordered_map::iterator type_it = classes.find(p_class); - ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(p_class)); + ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class))); ClassInfo &type = type_it->second; diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index 5a1bcb2b..6494bb93 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -49,8 +49,8 @@ void Variant::init_bindings() { to_type_constructor[i] = internal::gdn_interface->get_variant_to_type_constructor((GDNativeVariantType)i); } - String::init_bindings(); StringName::init_bindings(); + String::init_bindings(); NodePath::init_bindings(); RID::init_bindings(); Callable::init_bindings(); From ed4d3d36f9398c45e2b5a4e71b0af43d01c555b0 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Tue, 8 Nov 2022 21:56:36 +0100 Subject: [PATCH 7/7] Fix missing final newline in godot-headers/extension_api.json --- godot-headers/extension_api.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/godot-headers/extension_api.json b/godot-headers/extension_api.json index 65d1dc9d..c2ba1694 100644 --- a/godot-headers/extension_api.json +++ b/godot-headers/extension_api.json @@ -264388,4 +264388,4 @@ "format": "StringName signature;uint64_t call_count;uint64_t total_time;uint64_t self_time" } ] -} \ No newline at end of file +}