From 6185523a5dfee3389fc6c8bc0b73ca7c4494cf02 Mon Sep 17 00:00:00 2001 From: Daylily-Zeleen Date: Mon, 22 Apr 2024 22:34:44 +0800 Subject: [PATCH] Allow ClassDB to create a Object without postinitialization for GDExtension. --- core/crypto/crypto.cpp | 24 ++-- core/crypto/crypto.h | 16 +-- core/extension/gdextension.cpp | 60 ++++++++-- core/extension/gdextension.h | 6 +- core/extension/gdextension_interface.cpp | 10 ++ core/extension/gdextension_interface.h | 78 ++++++++++++- core/io/dtls_server.cpp | 6 +- core/io/dtls_server.h | 4 +- core/io/http_client.cpp | 4 +- core/io/http_client.h | 4 +- core/io/http_client_tcp.cpp | 6 +- core/io/http_client_tcp.h | 2 +- core/io/packet_peer_dtls.cpp | 6 +- core/io/packet_peer_dtls.h | 4 +- core/io/stream_peer_tls.cpp | 6 +- core/io/stream_peer_tls.h | 4 +- core/object/class_db.cpp | 103 +++++++++++++----- core/object/class_db.h | 21 +++- core/object/object.cpp | 8 +- core/object/object.h | 4 + modules/mbedtls/crypto_mbedtls.cpp | 16 +-- modules/mbedtls/crypto_mbedtls.h | 8 +- modules/mbedtls/dtls_server_mbedtls.cpp | 4 +- modules/mbedtls/dtls_server_mbedtls.h | 2 +- modules/mbedtls/packet_peer_mbed_dtls.cpp | 4 +- modules/mbedtls/packet_peer_mbed_dtls.h | 2 +- modules/mbedtls/stream_peer_mbedtls.cpp | 4 +- modules/mbedtls/stream_peer_mbedtls.h | 2 +- modules/mono/editor/bindings_generator.cpp | 2 +- .../GodotSharp/Core/GodotObject.base.cs | 7 +- .../Core/NativeInterop/NativeFuncs.cs | 2 +- modules/mono/glue/runtime_interop.cpp | 2 +- modules/webrtc/webrtc_peer_connection.cpp | 13 ++- modules/webrtc/webrtc_peer_connection.h | 2 +- modules/websocket/emws_peer.h | 2 +- modules/websocket/websocket_peer.cpp | 2 +- modules/websocket/websocket_peer.h | 6 +- modules/websocket/wsl_peer.h | 2 +- platform/web/http_client_web.cpp | 6 +- platform/web/http_client_web.h | 2 +- 40 files changed, 330 insertions(+), 136 deletions(-) diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index d3d007941057..62bacadf91aa 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -36,10 +36,10 @@ /// Resources -CryptoKey *(*CryptoKey::_create)() = nullptr; -CryptoKey *CryptoKey::create() { +CryptoKey *(*CryptoKey::_create)(bool p_notify_postinitialize) = nullptr; +CryptoKey *CryptoKey::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } return nullptr; } @@ -52,10 +52,10 @@ void CryptoKey::_bind_methods() { ClassDB::bind_method(D_METHOD("load_from_string", "string_key", "public_only"), &CryptoKey::load_from_string, DEFVAL(false)); } -X509Certificate *(*X509Certificate::_create)() = nullptr; -X509Certificate *X509Certificate::create() { +X509Certificate *(*X509Certificate::_create)(bool p_notify_postinitialize) = nullptr; +X509Certificate *X509Certificate::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } return nullptr; } @@ -116,10 +116,10 @@ void HMACContext::_bind_methods() { ClassDB::bind_method(D_METHOD("finish"), &HMACContext::finish); } -HMACContext *(*HMACContext::_create)() = nullptr; -HMACContext *HMACContext::create() { +HMACContext *(*HMACContext::_create)(bool p_notify_postinitialize) = nullptr; +HMACContext *HMACContext::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } ERR_FAIL_V_MSG(nullptr, "HMACContext is not available when the mbedtls module is disabled."); } @@ -127,10 +127,10 @@ HMACContext *HMACContext::create() { /// Crypto void (*Crypto::_load_default_certificates)(const String &p_path) = nullptr; -Crypto *(*Crypto::_create)() = nullptr; -Crypto *Crypto::create() { +Crypto *(*Crypto::_create)(bool p_notify_postinitialize) = nullptr; +Crypto *Crypto::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } ERR_FAIL_V_MSG(nullptr, "Crypto is not available when the mbedtls module is disabled."); } diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index 16649422cffb..c19e6b6773bb 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -42,10 +42,10 @@ class CryptoKey : public Resource { protected: static void _bind_methods(); - static CryptoKey *(*_create)(); + static CryptoKey *(*_create)(bool p_notify_postinitialize); public: - static CryptoKey *create(); + static CryptoKey *create(bool p_notify_postinitialize = true); virtual Error load(const String &p_path, bool p_public_only = false) = 0; virtual Error save(const String &p_path, bool p_public_only = false) = 0; virtual String save_to_string(bool p_public_only = false) = 0; @@ -58,10 +58,10 @@ class X509Certificate : public Resource { protected: static void _bind_methods(); - static X509Certificate *(*_create)(); + static X509Certificate *(*_create)(bool p_notify_postinitialize); public: - static X509Certificate *create(); + static X509Certificate *create(bool p_notify_postinitialize = true); virtual Error load(const String &p_path) = 0; virtual Error load_from_memory(const uint8_t *p_buffer, int p_len) = 0; virtual Error save(const String &p_path) = 0; @@ -106,10 +106,10 @@ class HMACContext : public RefCounted { protected: static void _bind_methods(); - static HMACContext *(*_create)(); + static HMACContext *(*_create)(bool p_notify_postinitialize); public: - static HMACContext *create(); + static HMACContext *create(bool p_notify_postinitialize = true); virtual Error start(HashingContext::HashType p_hash_type, const PackedByteArray &p_key) = 0; virtual Error update(const PackedByteArray &p_data) = 0; @@ -124,11 +124,11 @@ class Crypto : public RefCounted { protected: static void _bind_methods(); - static Crypto *(*_create)(); + static Crypto *(*_create)(bool p_notify_postinitialize); static void (*_load_default_certificates)(const String &p_path); public: - static Crypto *create(); + static Crypto *create(bool p_notify_postinitialize = true); static void load_default_certificates(const String &p_path); virtual PackedByteArray generate_random_bytes(int p_bytes) = 0; diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index cb6832ea3984..e016ddfaaaf9 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -382,7 +382,7 @@ class GDExtensionMethodBind : public MethodBind { #ifndef DISABLE_DEPRECATED void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) { - const GDExtensionClassCreationInfo3 class_info3 = { + const GDExtensionClassCreationInfo4 class_info4 = { p_extension_funcs->is_virtual, // GDExtensionBool is_virtual; p_extension_funcs->is_abstract, // GDExtensionBool is_abstract; true, // GDExtensionBool is_exposed; @@ -398,7 +398,7 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func; p_extension_funcs->reference_func, // GDExtensionClassReference reference_func; p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func; - p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ + nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */ p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ nullptr, // GDExtensionClassRecreateInstance recreate_instance_func; p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func; @@ -411,12 +411,13 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library const ClassCreationDeprecatedInfo legacy = { p_extension_funcs->notification_func, // GDExtensionClassNotification notification_func; p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func; + p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; }; - _register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info3, &legacy); + _register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy); } void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs) { - const GDExtensionClassCreationInfo3 class_info3 = { + const GDExtensionClassCreationInfo4 class_info4 = { p_extension_funcs->is_virtual, // GDExtensionBool is_virtual; p_extension_funcs->is_abstract, // GDExtensionBool is_abstract; p_extension_funcs->is_exposed, // GDExtensionBool is_exposed; @@ -432,7 +433,7 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func; p_extension_funcs->reference_func, // GDExtensionClassReference reference_func; p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func; - p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ + nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */ p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ p_extension_funcs->recreate_instance_func, // GDExtensionClassRecreateInstance recreate_instance_func; p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func; @@ -445,16 +446,53 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar const ClassCreationDeprecatedInfo legacy = { nullptr, // GDExtensionClassNotification notification_func; p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func; + p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; }; - _register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info3, &legacy); + _register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy); } -#endif // DISABLE_DEPRECATED void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs) { + const GDExtensionClassCreationInfo4 class_info4 = { + p_extension_funcs->is_virtual, // GDExtensionBool is_virtual; + p_extension_funcs->is_abstract, // GDExtensionBool is_abstract; + p_extension_funcs->is_exposed, // GDExtensionBool is_exposed; + p_extension_funcs->is_runtime, // GDExtensionBool is_runtime; + p_extension_funcs->set_func, // GDExtensionClassSet set_func; + p_extension_funcs->get_func, // GDExtensionClassGet get_func; + p_extension_funcs->get_property_list_func, // GDExtensionClassGetPropertyList get_property_list_func; + p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func; + p_extension_funcs->property_can_revert_func, // GDExtensionClassPropertyCanRevert property_can_revert_func; + p_extension_funcs->property_get_revert_func, // GDExtensionClassPropertyGetRevert property_get_revert_func; + p_extension_funcs->validate_property_func, // GDExtensionClassValidateProperty validate_property_func; + p_extension_funcs->notification_func, // GDExtensionClassNotification2 notification_func; + p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func; + p_extension_funcs->reference_func, // GDExtensionClassReference reference_func; + p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func; + nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */ + p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ + p_extension_funcs->recreate_instance_func, // GDExtensionClassRecreateInstance recreate_instance_func; + p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func; + p_extension_funcs->get_virtual_call_data_func, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func; + p_extension_funcs->call_virtual_with_data_func, // GDExtensionClassCallVirtualWithData call_virtual_func; + p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid; + p_extension_funcs->class_userdata, // void *class_userdata; + }; + + const ClassCreationDeprecatedInfo legacy = { + nullptr, // GDExtensionClassNotification notification_func; + nullptr, // GDExtensionClassFreePropertyList free_property_list_func; + p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance2 create_instance_func; + }; + _register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy); +} + +#endif // DISABLE_DEPRECATED + +void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs) { _register_extension_class_internal(p_library, p_class_name, p_parent_class_name, p_extension_funcs); } -void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs) { +void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs) { GDExtension *self = reinterpret_cast(p_library); StringName class_name = *reinterpret_cast(p_class_name); @@ -530,6 +568,7 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr if (p_deprecated_funcs) { extension->gdextension.notification = p_deprecated_funcs->notification_func; extension->gdextension.free_property_list = p_deprecated_funcs->free_property_list_func; + extension->gdextension.create_instance = p_deprecated_funcs->create_instance_func; } #endif // DISABLE_DEPRECATED extension->gdextension.notification2 = p_extension_funcs->notification_func; @@ -537,7 +576,7 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr extension->gdextension.reference = p_extension_funcs->reference_func; extension->gdextension.unreference = p_extension_funcs->unreference_func; extension->gdextension.class_userdata = p_extension_funcs->class_userdata; - extension->gdextension.create_instance = p_extension_funcs->create_instance_func; + extension->gdextension.create_instance2 = p_extension_funcs->create_instance_func; extension->gdextension.free_instance = p_extension_funcs->free_instance_func; extension->gdextension.recreate_instance = p_extension_funcs->recreate_instance_func; extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func; @@ -888,8 +927,9 @@ void GDExtension::initialize_gdextensions() { #ifndef DISABLE_DEPRECATED register_interface_function("classdb_register_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class); register_interface_function("classdb_register_extension_class2", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class2); -#endif // DISABLE_DEPRECATED register_interface_function("classdb_register_extension_class3", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class3); +#endif // DISABLE_DEPRECATED + register_interface_function("classdb_register_extension_class4", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class4); register_interface_function("classdb_register_extension_class_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_method); register_interface_function("classdb_register_extension_class_virtual_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_virtual_method); register_interface_function("classdb_register_extension_class_integer_constant", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_integer_constant); diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h index 9393e7399ba2..20fe27b8a87e 100644 --- a/core/extension/gdextension.h +++ b/core/extension/gdextension.h @@ -72,15 +72,17 @@ class GDExtension : public Resource { #ifndef DISABLE_DEPRECATED GDExtensionClassNotification notification_func = nullptr; GDExtensionClassFreePropertyList free_property_list_func = nullptr; + GDExtensionClassCreateInstance create_instance_func = nullptr; #endif // DISABLE_DEPRECATED }; #ifndef DISABLE_DEPRECATED static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs); static void _register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs); -#endif // DISABLE_DEPRECATED static void _register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs); - static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr); +#endif // DISABLE_DEPRECATED + static void _register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs); + static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr); static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info); static void _register_extension_class_virtual_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassVirtualMethodInfo *p_method_info); static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield); diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index 85f83eecfddf..a5a0fc906aa4 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -1515,10 +1515,17 @@ static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionC return (GDExtensionMethodBindPtr)mb; } +#ifndef DISABLE_DEPRECATED static GDExtensionObjectPtr gdextension_classdb_construct_object(GDExtensionConstStringNamePtr p_classname) { const StringName classname = *reinterpret_cast(p_classname); return (GDExtensionObjectPtr)ClassDB::instantiate_no_placeholders(classname); } +#endif + +static GDExtensionObjectPtr gdextension_classdb_construct_object2(GDExtensionConstStringNamePtr p_classname) { + const StringName classname = *reinterpret_cast(p_classname); + return (GDExtensionObjectPtr)ClassDB::instantiate_without_postinitialization(classname); +} static void *gdextension_classdb_get_class_tag(GDExtensionConstStringNamePtr p_classname) { const StringName classname = *reinterpret_cast(p_classname); @@ -1701,7 +1708,10 @@ void gdextension_setup_interface() { #endif // DISABLE_DEPRECATED REGISTER_INTERFACE_FUNC(callable_custom_create2); REGISTER_INTERFACE_FUNC(callable_custom_get_userdata); +#ifndef DISABLE_DEPRECATED REGISTER_INTERFACE_FUNC(classdb_construct_object); +#endif // DISABLE_DEPRECATED + REGISTER_INTERFACE_FUNC(classdb_construct_object2); REGISTER_INTERFACE_FUNC(classdb_get_method_bind); REGISTER_INTERFACE_FUNC(classdb_get_class_tag); REGISTER_INTERFACE_FUNC(editor_add_plugin); diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index fce377f96738..cac76d39bdb9 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -268,6 +268,7 @@ typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_class_userdata); +typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance2)(void *p_class_userdata, bool p_notify_postinitialize); typedef void (*GDExtensionClassFreeInstance)(void *p_class_userdata, GDExtensionClassInstancePtr p_instance); typedef GDExtensionClassInstancePtr (*GDExtensionClassRecreateInstance)(void *p_class_userdata, GDExtensionObjectPtr p_object); typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name); @@ -292,7 +293,7 @@ typedef struct { GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function. GDExtensionClassGetRID get_rid_func; void *class_userdata; // Per-class user data, later accessible in instance bindings. -} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo3 instead. +} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo4 instead. typedef struct { GDExtensionBool is_virtual; @@ -325,7 +326,7 @@ typedef struct { GDExtensionClassCallVirtualWithData call_virtual_with_data_func; GDExtensionClassGetRID get_rid_func; void *class_userdata; // Per-class user data, later accessible in instance bindings. -} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo3 instead. +} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo4 instead. typedef struct { GDExtensionBool is_virtual; @@ -359,7 +360,41 @@ typedef struct { GDExtensionClassCallVirtualWithData call_virtual_with_data_func; GDExtensionClassGetRID get_rid_func; void *class_userdata; // Per-class user data, later accessible in instance bindings. -} GDExtensionClassCreationInfo3; +} GDExtensionClassCreationInfo3; // Deprecated. Use GDExtensionClassCreationInfo4 instead. + +typedef struct { + GDExtensionBool is_virtual; + GDExtensionBool is_abstract; + GDExtensionBool is_exposed; + GDExtensionBool is_runtime; + GDExtensionClassSet set_func; + GDExtensionClassGet get_func; + GDExtensionClassGetPropertyList get_property_list_func; + GDExtensionClassFreePropertyList2 free_property_list_func; + GDExtensionClassPropertyCanRevert property_can_revert_func; + GDExtensionClassPropertyGetRevert property_get_revert_func; + GDExtensionClassValidateProperty validate_property_func; + GDExtensionClassNotification2 notification_func; + GDExtensionClassToString to_string_func; + GDExtensionClassReference reference_func; + GDExtensionClassUnreference unreference_func; + GDExtensionClassCreateInstance2 create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract. + GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory. + GDExtensionClassRecreateInstance recreate_instance_func; + // Queries a virtual function by name and returns a callback to invoke the requested virtual function. + GDExtensionClassGetVirtual get_virtual_func; + // Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that + // need or benefit from extra data when calling virtual functions. + // Returns user data that will be passed to `call_virtual_with_data_func`. + // Returning `NULL` from this function signals to Godot that the virtual function is not overridden. + // Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized. + // You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`. + GDExtensionClassGetVirtualCallData get_virtual_call_data_func; + // Used to call virtual functions when `get_virtual_call_data_func` is not null. + GDExtensionClassCallVirtualWithData call_virtual_with_data_func; + GDExtensionClassGetRID get_rid_func; + void *class_userdata; // Per-class user data, later accessible in instance bindings. +} GDExtensionClassCreationInfo4; typedef void *GDExtensionClassLibraryPtr; @@ -2680,6 +2715,7 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT /** * @name classdb_construct_object * @since 4.1 + * @deprecated in Godot 4.4. Use `classdb_construct_object2` instead. * * Constructs an Object of the requested class. * @@ -2691,6 +2727,22 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT */ typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject)(GDExtensionConstStringNamePtr p_classname); +/** + * @name classdb_construct_object2 + * @since 4.4 + * + * Constructs an Object of the requested class. + * + * The passed class must be a built-in godot class, or an already-registered extension class. In both cases, object_set_instance() should be called to fully initialize the object. + * + * "NOTIFICATION_POSTINITIALIZE" must be sent after construction. + * + * @param p_classname A pointer to a StringName with the class name. + * + * @return A pointer to the newly created Object. + */ +typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject2)(GDExtensionConstStringNamePtr p_classname); + /** * @name classdb_get_method_bind * @since 4.1 @@ -2722,7 +2774,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa /** * @name classdb_register_extension_class * @since 4.1 - * @deprecated in Godot 4.2. Use `classdb_register_extension_class3` instead. + * @deprecated in Godot 4.2. Use `classdb_register_extension_class4` instead. * * Registers an extension class in the ClassDB. * @@ -2738,7 +2790,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla /** * @name classdb_register_extension_class2 * @since 4.2 - * @deprecated in Godot 4.3. Use `classdb_register_extension_class3` instead. + * @deprecated in Godot 4.3. Use `classdb_register_extension_class4` instead. * * Registers an extension class in the ClassDB. * @@ -2754,6 +2806,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl /** * @name classdb_register_extension_class3 * @since 4.3 + * @deprecated in Godot 4.4. Use `classdb_register_extension_class4` instead. * * Registers an extension class in the ClassDB. * @@ -2766,6 +2819,21 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl */ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass3)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs); +/** + * @name classdb_register_extension_class4 + * @since 4.4 + * + * Registers an extension class in the ClassDB. + * + * Provided struct can be safely freed once the function returns. + * + * @param p_library A pointer the library received by the GDExtension's entry point function. + * @param p_class_name A pointer to a StringName with the class name. + * @param p_parent_class_name A pointer to a StringName with the parent class name. + * @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo2 struct. + */ +typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass4)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs); + /** * @name classdb_register_extension_class_method * @since 4.1 diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp index 07d62d3a8d47..7638328dc33e 100644 --- a/core/io/dtls_server.cpp +++ b/core/io/dtls_server.cpp @@ -33,12 +33,12 @@ #include "core/config/project_settings.h" #include "core/io/file_access.h" -DTLSServer *(*DTLSServer::_create)() = nullptr; +DTLSServer *(*DTLSServer::_create)(bool p_notify_postinitialize) = nullptr; bool DTLSServer::available = false; -DTLSServer *DTLSServer::create() { +DTLSServer *DTLSServer::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } return nullptr; } diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h index f3fbde3c152a..5ffed1ecc381 100644 --- a/core/io/dtls_server.h +++ b/core/io/dtls_server.h @@ -38,14 +38,14 @@ class DTLSServer : public RefCounted { GDCLASS(DTLSServer, RefCounted); protected: - static DTLSServer *(*_create)(); + static DTLSServer *(*_create)(bool p_notify_postinitialize); static void _bind_methods(); static bool available; public: static bool is_available(); - static DTLSServer *create(); + static DTLSServer *create(bool p_notify_postinitialize = true); virtual Error setup(Ref p_options) = 0; virtual void stop() = 0; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 833fd1adc381..fc91341bedda 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -42,9 +42,9 @@ const char *HTTPClient::_methods[METHOD_MAX] = { "PATCH" }; -HTTPClient *HTTPClient::create() { +HTTPClient *HTTPClient::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } return nullptr; } diff --git a/core/io/http_client.h b/core/io/http_client.h index 9e018182e379..594529112213 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -158,12 +158,12 @@ class HTTPClient : public RefCounted { Error _request_raw(Method p_method, const String &p_url, const Vector &p_headers, const Vector &p_body); Error _request(Method p_method, const String &p_url, const Vector &p_headers, const String &p_body = String()); - static HTTPClient *(*_create)(); + static HTTPClient *(*_create)(bool p_notify_postinitialize); static void _bind_methods(); public: - static HTTPClient *create(); + static HTTPClient *create(bool p_notify_postinitialize = true); String query_string_from_dict(const Dictionary &p_dict); Error verify_headers(const Vector &p_headers); diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp index 2f45238951be..70fcad543a1f 100644 --- a/core/io/http_client_tcp.cpp +++ b/core/io/http_client_tcp.cpp @@ -35,8 +35,8 @@ #include "core/io/stream_peer_tls.h" #include "core/version.h" -HTTPClient *HTTPClientTCP::_create_func() { - return memnew(HTTPClientTCP); +HTTPClient *HTTPClientTCP::_create_func(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, Ref p_options) { @@ -792,6 +792,6 @@ HTTPClientTCP::HTTPClientTCP() { request_buffer.instantiate(); } -HTTPClient *(*HTTPClient::_create)() = HTTPClientTCP::_create_func; +HTTPClient *(*HTTPClient::_create)(bool p_notify_postinitialize) = HTTPClientTCP::_create_func; #endif // WEB_ENABLED diff --git a/core/io/http_client_tcp.h b/core/io/http_client_tcp.h index 6060c975bcb8..dd6cc6b84f04 100644 --- a/core/io/http_client_tcp.h +++ b/core/io/http_client_tcp.h @@ -76,7 +76,7 @@ class HTTPClientTCP : public HTTPClient { Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received); public: - static HTTPClient *_create_func(); + static HTTPClient *_create_func(bool p_notify_postinitialize); Error request(Method p_method, const String &p_url, const Vector &p_headers, const uint8_t *p_body, int p_body_size) override; diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp index 18bef3ff3cca..231c48d88765 100644 --- a/core/io/packet_peer_dtls.cpp +++ b/core/io/packet_peer_dtls.cpp @@ -32,12 +32,12 @@ #include "core/config/project_settings.h" #include "core/io/file_access.h" -PacketPeerDTLS *(*PacketPeerDTLS::_create)() = nullptr; +PacketPeerDTLS *(*PacketPeerDTLS::_create)(bool p_notify_postinitialize) = nullptr; bool PacketPeerDTLS::available = false; -PacketPeerDTLS *PacketPeerDTLS::create() { +PacketPeerDTLS *PacketPeerDTLS::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } return nullptr; } diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h index 3990a851f744..03d97a59036c 100644 --- a/core/io/packet_peer_dtls.h +++ b/core/io/packet_peer_dtls.h @@ -38,7 +38,7 @@ class PacketPeerDTLS : public PacketPeer { GDCLASS(PacketPeerDTLS, PacketPeer); protected: - static PacketPeerDTLS *(*_create)(); + static PacketPeerDTLS *(*_create)(bool p_notify_postinitialize); static void _bind_methods(); static bool available; @@ -57,7 +57,7 @@ class PacketPeerDTLS : public PacketPeer { virtual void disconnect_from_peer() = 0; virtual Status get_status() const = 0; - static PacketPeerDTLS *create(); + static PacketPeerDTLS *create(bool p_notify_postinitialize = true); static bool is_available(); PacketPeerDTLS() {} diff --git a/core/io/stream_peer_tls.cpp b/core/io/stream_peer_tls.cpp index 69877974e685..f04e217a266b 100644 --- a/core/io/stream_peer_tls.cpp +++ b/core/io/stream_peer_tls.cpp @@ -32,11 +32,11 @@ #include "core/config/engine.h" -StreamPeerTLS *(*StreamPeerTLS::_create)() = nullptr; +StreamPeerTLS *(*StreamPeerTLS::_create)(bool p_notify_postinitialize) = nullptr; -StreamPeerTLS *StreamPeerTLS::create() { +StreamPeerTLS *StreamPeerTLS::create(bool p_notify_postinitialize) { if (_create) { - return _create(); + return _create(p_notify_postinitialize); } return nullptr; } diff --git a/core/io/stream_peer_tls.h b/core/io/stream_peer_tls.h index 5894abb7a465..3e03e25a2d42 100644 --- a/core/io/stream_peer_tls.h +++ b/core/io/stream_peer_tls.h @@ -38,7 +38,7 @@ class StreamPeerTLS : public StreamPeer { GDCLASS(StreamPeerTLS, StreamPeer); protected: - static StreamPeerTLS *(*_create)(); + static StreamPeerTLS *(*_create)(bool p_notify_postinitialize); static void _bind_methods(); public: @@ -58,7 +58,7 @@ class StreamPeerTLS : public StreamPeer { virtual void disconnect_from_stream() = 0; - static StreamPeerTLS *create(); + static StreamPeerTLS *create(bool p_notify_postinitialize = true); static bool is_available(); diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index ceeb04b8eae3..6e13f69c2c8f 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -181,7 +181,7 @@ class PlaceholderExtensionInstance { return 0; } - static GDExtensionObjectPtr placeholder_class_create_instance(void *p_class_userdata) { + static GDExtensionObjectPtr placeholder_class_create_instance(void *p_class_userdata, bool p_notify_postinitialize) { ClassDB::ClassInfo *ti = (ClassDB::ClassInfo *)p_class_userdata; // Find the closest native parent, that isn't a runtime class. @@ -192,7 +192,7 @@ class PlaceholderExtensionInstance { ERR_FAIL_NULL_V(native_parent->creation_func, nullptr); // Construct a placeholder. - Object *obj = native_parent->creation_func(); + Object *obj = native_parent->creation_func(p_notify_postinitialize); // ClassDB::set_object_extension_instance() won't be called for placeholders. // We need need to make sure that all the things it would have done (even if @@ -502,12 +502,12 @@ StringName ClassDB::get_compatibility_class(const StringName &p_class) { return StringName(); } -Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require_real_class) { +Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require_real_class, bool p_notify_postinitialize) { ClassInfo *ti; { OBJTYPE_RLOCK; ti = classes.getptr(p_class); - if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) { + if (!_can_instantiate(ti)) { if (compat_classes.has(p_class)) { ti = classes.getptr(compat_classes[p_class]); } @@ -516,34 +516,78 @@ Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, "Class '" + String(p_class) + "' is disabled."); ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, "Class '" + String(p_class) + "' or its base class cannot be instantiated."); } + #ifdef TOOLS_ENABLED if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) { ERR_PRINT("Class '" + String(p_class) + "' can only be instantiated by editor."); return nullptr; } #endif - if (ti->gdextension && ti->gdextension->create_instance) { - ObjectGDExtension *extension = ti->gdextension; -#ifdef TOOLS_ENABLED - if (!p_require_real_class && ti->is_runtime && Engine::get_singleton()->is_editor_hint()) { - extension = get_placeholder_extension(ti->name); - } -#endif - return (Object *)extension->create_instance(extension->class_userdata); - } else { + #ifdef TOOLS_ENABLED - if (!p_require_real_class && ti->is_runtime && Engine::get_singleton()->is_editor_hint()) { - if (!ti->inherits_ptr || !ti->inherits_ptr->creation_func) { - ERR_PRINT(vformat("Cannot make a placeholder instance of runtime class %s because its parent cannot be constructed.", ti->name)); - } else { - ObjectGDExtension *extension = get_placeholder_extension(ti->name); - return (Object *)extension->create_instance(extension->class_userdata); + // Try to create placeholder. + if (!p_require_real_class && ti->is_runtime && Engine::get_singleton()->is_editor_hint()) { + bool can_create_placeholder = false; + if (ti->gdextension) { + if (ti->gdextension->create_instance2) { + can_create_placeholder = true; } +#ifndef DISABLE_DEPRECATED + else if (ti->gdextension->create_instance) { + can_create_placeholder = true; + } +#endif // DISABLE_DEPRECATED + } else if (!ti->inherits_ptr || !ti->inherits_ptr->creation_func) { + ERR_PRINT(vformat("Cannot make a placeholder instance of runtime class %s because its parent cannot be constructed.", ti->name)); + } else { + can_create_placeholder = true; } -#endif - return ti->creation_func(); + if (can_create_placeholder) { + ObjectGDExtension *extension = get_placeholder_extension(ti->name); + return (Object *)extension->create_instance2(extension->class_userdata, p_notify_postinitialize); + } + } +#endif // TOOLS_ENABLED + + if (ti->gdextension && ti->gdextension->create_instance2) { + ObjectGDExtension *extension = ti->gdextension; + return (Object *)extension->create_instance2(extension->class_userdata, p_notify_postinitialize); + } +#ifndef DISABLE_DEPRECATED + else if (ti->gdextension && ti->gdextension->create_instance) { + ObjectGDExtension *extension = ti->gdextension; + return (Object *)extension->create_instance(extension->class_userdata); + } +#endif // DISABLE_DEPRECATED + else { + return ti->creation_func(p_notify_postinitialize); + } +} + +bool ClassDB::_can_instantiate(ClassInfo *p_class_info) { + if (!p_class_info) { + return false; + } + + if (p_class_info->disabled || !p_class_info->creation_func) { + return false; + } + + if (!p_class_info->gdextension) { + return true; } + + if (p_class_info->gdextension->create_instance2) { + return true; + } + +#ifndef DISABLE_DEPRECATED + if (p_class_info->gdextension->create_instance) { + return true; + } +#endif // DISABLE_DEPRECATED + return false; } Object *ClassDB::instantiate(const StringName &p_class) { @@ -554,6 +598,10 @@ Object *ClassDB::instantiate_no_placeholders(const StringName &p_class) { return _instantiate_internal(p_class, true); } +Object *ClassDB::instantiate_without_postinitialization(const StringName &p_class) { + return _instantiate_internal(p_class, true, false); +} + #ifdef TOOLS_ENABLED ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class) { ObjectGDExtension *placeholder_extension = placeholder_extensions.getptr(p_class); @@ -565,7 +613,7 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class) { OBJTYPE_RLOCK; ti = classes.getptr(p_class); - if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) { + if (!_can_instantiate(ti)) { if (compat_classes.has(p_class)) { ti = classes.getptr(compat_classes[p_class]); } @@ -626,7 +674,10 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class) placeholder_extension->get_rid = &PlaceholderExtensionInstance::placeholder_instance_get_rid; placeholder_extension->class_userdata = ti; - placeholder_extension->create_instance = &PlaceholderExtensionInstance::placeholder_class_create_instance; +#ifndef DISABLE_DEPRECATED + placeholder_extension->create_instance = nullptr; +#endif // DISABLE_DEPRECATED + placeholder_extension->create_instance2 = &PlaceholderExtensionInstance::placeholder_class_create_instance; placeholder_extension->free_instance = &PlaceholderExtensionInstance::placeholder_class_free_instance; placeholder_extension->get_virtual = &PlaceholderExtensionInstance::placeholder_class_get_virtual; placeholder_extension->get_virtual_call_data = nullptr; @@ -643,7 +694,7 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName & { OBJTYPE_RLOCK; ti = classes.getptr(p_class); - if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) { + if (!_can_instantiate(ti)) { if (compat_classes.has(p_class)) { ti = classes.getptr(compat_classes[p_class]); } @@ -680,7 +731,7 @@ bool ClassDB::can_instantiate(const StringName &p_class) { return false; } #endif - return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance)); + return _can_instantiate(ti); } bool ClassDB::is_abstract(const StringName &p_class) { @@ -715,7 +766,7 @@ bool ClassDB::is_virtual(const StringName &p_class) { return false; } #endif - return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance) && ti->is_virtual); + return (_can_instantiate(ti) && ti->is_virtual); } void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) { diff --git a/core/object/class_db.h b/core/object/class_db.h index 228b82b588cc..68f3f4550bfa 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -134,15 +134,21 @@ class ClassDB { bool reloadable = false; bool is_virtual = false; bool is_runtime = false; - Object *(*creation_func)() = nullptr; + // The bool argument indicates the need to postinitialize. + Object *(*creation_func)(bool) = nullptr; ClassInfo() {} ~ClassInfo() {} }; template - static Object *creator() { - return memnew(T); + static Object *creator(bool p_notify_postinitialize) { + Object *ret = new ("") T; + ret->_initialize(); + if (p_notify_postinitialize) { + ret->_postinitialize(); + } + return ret; } static RWLock lock; @@ -183,7 +189,9 @@ class ClassDB { static MethodBind *_bind_vararg_method(MethodBind *p_bind, const StringName &p_name, const Vector &p_default_args, bool p_compatibility); static void _bind_method_custom(const StringName &p_class, MethodBind *p_method, bool p_compatibility); - static Object *_instantiate_internal(const StringName &p_class, bool p_require_real_class = false); + static Object *_instantiate_internal(const StringName &p_class, bool p_require_real_class = false, bool p_notify_postinitialize = true); + + static bool _can_instantiate(ClassInfo *p_class_info); public: // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! @@ -256,8 +264,8 @@ class ClassDB { static void unregister_extension_class(const StringName &p_class, bool p_free_method_binds = true); template - static Object *_create_ptr_func() { - return T::create(); + static Object *_create_ptr_func(bool p_notify_postinitialize) { + return T::create(p_notify_postinitialize); } template @@ -291,6 +299,7 @@ class ClassDB { static bool is_virtual(const StringName &p_class); static Object *instantiate(const StringName &p_class); static Object *instantiate_no_placeholders(const StringName &p_class); + static Object *instantiate_without_postinitialization(const StringName &p_class); static void set_object_extension_instance(Object *p_object, const StringName &p_class, GDExtensionClassInstancePtr p_instance); static APIType get_api_type(const StringName &p_class); diff --git a/core/object/object.cpp b/core/object/object.cpp index a2926a478d70..161b1e3dbeea 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -207,10 +207,13 @@ void Object::cancel_free() { _predelete_ok = false; } -void Object::_postinitialize() { - _class_name_ptr = _get_class_namev(); // Set the direct pointer, which is much faster to obtain, but can only happen after postinitialize. +void Object::_initialize() { + _class_name_ptr = _get_class_namev(); // Set the direct pointer, which is much faster to obtain, but can only happen after _initialize. _initialize_classv(); _class_name_ptr = nullptr; // May have been called from a constructor. +} + +void Object::_postinitialize() { notification(NOTIFICATION_POSTINITIALIZE); } @@ -2129,6 +2132,7 @@ bool predelete_handler(Object *p_object) { } void postinitialize_handler(Object *p_object) { + p_object->_initialize(); p_object->_postinitialize(); } diff --git a/core/object/object.h b/core/object/object.h index adb50268d2ad..7307b7ede074 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -350,7 +350,10 @@ struct ObjectGDExtension { } void *class_userdata = nullptr; +#ifndef DISABLE_DEPRECATED GDExtensionClassCreateInstance create_instance; +#endif // DISABLE_DEPRECATED + GDExtensionClassCreateInstance2 create_instance2; GDExtensionClassFreeInstance free_instance; GDExtensionClassGetVirtual get_virtual; GDExtensionClassGetVirtualCallData get_virtual_call_data; @@ -632,6 +635,7 @@ class Object { int _predelete_ok = 0; ObjectID _instance_id; bool _predelete(); + void _initialize(); void _postinitialize(); bool _can_translate = true; bool _emitting = false; diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp index e910627b3248..0d97b5fc1a2d 100644 --- a/modules/mbedtls/crypto_mbedtls.cpp +++ b/modules/mbedtls/crypto_mbedtls.cpp @@ -49,8 +49,8 @@ #define PEM_END_CRT "-----END CERTIFICATE-----\n" #define PEM_MIN_SIZE 54 -CryptoKey *CryptoKeyMbedTLS::create() { - return memnew(CryptoKeyMbedTLS); +CryptoKey *CryptoKeyMbedTLS::create(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } Error CryptoKeyMbedTLS::load(const String &p_path, bool p_public_only) { @@ -153,8 +153,8 @@ int CryptoKeyMbedTLS::_parse_key(const uint8_t *p_buf, int p_size) { #endif } -X509Certificate *X509CertificateMbedTLS::create() { - return memnew(X509CertificateMbedTLS); +X509Certificate *X509CertificateMbedTLS::create(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } Error X509CertificateMbedTLS::load(const String &p_path) { @@ -250,8 +250,8 @@ bool HMACContextMbedTLS::is_md_type_allowed(mbedtls_md_type_t p_md_type) { } } -HMACContext *HMACContextMbedTLS::create() { - return memnew(HMACContextMbedTLS); +HMACContext *HMACContextMbedTLS::create(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } Error HMACContextMbedTLS::start(HashingContext::HashType p_hash_type, const PackedByteArray &p_key) { @@ -309,8 +309,8 @@ HMACContextMbedTLS::~HMACContextMbedTLS() { } } -Crypto *CryptoMbedTLS::create() { - return memnew(CryptoMbedTLS); +Crypto *CryptoMbedTLS::create(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } void CryptoMbedTLS::initialize_crypto() { diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h index 52918cedf036..5e1da550d775 100644 --- a/modules/mbedtls/crypto_mbedtls.h +++ b/modules/mbedtls/crypto_mbedtls.h @@ -49,7 +49,7 @@ class CryptoKeyMbedTLS : public CryptoKey { int _parse_key(const uint8_t *p_buf, int p_size); public: - static CryptoKey *create(); + static CryptoKey *create(bool p_notify_postinitialize = true); static void make_default() { CryptoKey::_create = create; } static void finalize() { CryptoKey::_create = nullptr; } @@ -80,7 +80,7 @@ class X509CertificateMbedTLS : public X509Certificate { int locks; public: - static X509Certificate *create(); + static X509Certificate *create(bool p_notify_postinitialize = true); static void make_default() { X509Certificate::_create = create; } static void finalize() { X509Certificate::_create = nullptr; } @@ -112,7 +112,7 @@ class HMACContextMbedTLS : public HMACContext { void *ctx = nullptr; public: - static HMACContext *create(); + static HMACContext *create(bool p_notify_postinitialize = true); static void make_default() { HMACContext::_create = create; } static void finalize() { HMACContext::_create = nullptr; } @@ -133,7 +133,7 @@ class CryptoMbedTLS : public Crypto { static X509CertificateMbedTLS *default_certs; public: - static Crypto *create(); + static Crypto *create(bool p_notify_postinitialize = true); static void initialize_crypto(); static void finalize_crypto(); static X509CertificateMbedTLS *get_default_certificates(); diff --git a/modules/mbedtls/dtls_server_mbedtls.cpp b/modules/mbedtls/dtls_server_mbedtls.cpp index e466fe15d6d1..b64bdcb1921d 100644 --- a/modules/mbedtls/dtls_server_mbedtls.cpp +++ b/modules/mbedtls/dtls_server_mbedtls.cpp @@ -54,8 +54,8 @@ Ref DTLSServerMbedTLS::take_connection(Ref p_udp_ return out; } -DTLSServer *DTLSServerMbedTLS::_create_func() { - return memnew(DTLSServerMbedTLS); +DTLSServer *DTLSServerMbedTLS::_create_func(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } void DTLSServerMbedTLS::initialize() { diff --git a/modules/mbedtls/dtls_server_mbedtls.h b/modules/mbedtls/dtls_server_mbedtls.h index 59befecf4373..18661bf50551 100644 --- a/modules/mbedtls/dtls_server_mbedtls.h +++ b/modules/mbedtls/dtls_server_mbedtls.h @@ -37,7 +37,7 @@ class DTLSServerMbedTLS : public DTLSServer { private: - static DTLSServer *_create_func(); + static DTLSServer *_create_func(bool p_notify_postinitialize); Ref tls_options; Ref cookies; diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp index c7373481ca06..62d27405d877 100644 --- a/modules/mbedtls/packet_peer_mbed_dtls.cpp +++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp @@ -270,8 +270,8 @@ PacketPeerMbedDTLS::Status PacketPeerMbedDTLS::get_status() const { return status; } -PacketPeerDTLS *PacketPeerMbedDTLS::_create_func() { - return memnew(PacketPeerMbedDTLS); +PacketPeerDTLS *PacketPeerMbedDTLS::_create_func(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } void PacketPeerMbedDTLS::initialize_dtls() { diff --git a/modules/mbedtls/packet_peer_mbed_dtls.h b/modules/mbedtls/packet_peer_mbed_dtls.h index 2cff7a3589a3..881a5fdd0e40 100644 --- a/modules/mbedtls/packet_peer_mbed_dtls.h +++ b/modules/mbedtls/packet_peer_mbed_dtls.h @@ -50,7 +50,7 @@ class PacketPeerMbedDTLS : public PacketPeerDTLS { Ref base; - static PacketPeerDTLS *_create_func(); + static PacketPeerDTLS *_create_func(bool p_notify_postinitialize); static int bio_recv(void *ctx, unsigned char *buf, size_t len); static int bio_send(void *ctx, const unsigned char *buf, size_t len); diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp index a359b420411e..b4200410fb1c 100644 --- a/modules/mbedtls/stream_peer_mbedtls.cpp +++ b/modules/mbedtls/stream_peer_mbedtls.cpp @@ -295,8 +295,8 @@ Ref StreamPeerMbedTLS::get_stream() const { return base; } -StreamPeerTLS *StreamPeerMbedTLS::_create_func() { - return memnew(StreamPeerMbedTLS); +StreamPeerTLS *StreamPeerMbedTLS::_create_func(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } void StreamPeerMbedTLS::initialize_tls() { diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h index a8080f0960a0..b4f80b614c63 100644 --- a/modules/mbedtls/stream_peer_mbedtls.h +++ b/modules/mbedtls/stream_peer_mbedtls.h @@ -42,7 +42,7 @@ class StreamPeerMbedTLS : public StreamPeerTLS { Ref base; - static StreamPeerTLS *_create_func(); + static StreamPeerTLS *_create_func(bool p_notify_postinitialize); static int bio_recv(void *ctx, unsigned char *buf, size_t len); static int bio_send(void *ctx, const unsigned char *buf, size_t len); diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 9a76a256395b..b26f6d1bbf97 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2184,7 +2184,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // Add native constructor static field output << MEMBER_BEGIN << "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n" - << INDENT1 "private static readonly unsafe delegate* unmanaged " + << INDENT1 "private static readonly unsafe delegate* unmanaged " << CS_STATIC_FIELD_NATIVE_CTOR " = " ICALL_CLASSDB_GET_CONSTRUCTOR << "(" BINDINGS_NATIVE_NAME_FIELD ");\n"; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs index 0be9cdc953b4..c094eaed7787 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs @@ -30,7 +30,7 @@ public GodotObject() : this(false) } internal unsafe void ConstructAndInitialize( - delegate* unmanaged nativeCtor, + delegate* unmanaged nativeCtor, StringName nativeName, Type cachedType, bool refCounted @@ -40,7 +40,8 @@ bool refCounted { Debug.Assert(nativeCtor != null); - NativePtr = nativeCtor(); + // Need postinitialization. + NativePtr = nativeCtor(godot_bool.True); InteropUtils.TieManagedToUnmanaged(this, NativePtr, nativeName, refCounted, GetType(), cachedType); @@ -260,7 +261,7 @@ internal static IntPtr ClassDB_get_method_with_compatibility(StringName type, St return methodBind; } - internal static unsafe delegate* unmanaged ClassDB_get_constructor(StringName type) + internal static unsafe delegate* unmanaged ClassDB_get_constructor(StringName type) { // for some reason the '??' operator doesn't support 'delegate*' var typeSelf = (godot_string_name)type.NativeValue; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index cfd9ed7acc2b..6a643833f6a5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -47,7 +47,7 @@ public static partial IntPtr godotsharp_method_bind_get_method(in godot_string_n public static partial IntPtr godotsharp_method_bind_get_method_with_compatibility( in godot_string_name p_classname, in godot_string_name p_methodname, ulong p_hash); - public static partial delegate* unmanaged godotsharp_get_class_constructor( + public static partial delegate* unmanaged godotsharp_get_class_constructor( in godot_string_name p_classname); public static partial IntPtr godotsharp_engine_get_singleton(in godot_string p_name); diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 80e9fdf77f5d..73c10eba830a 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -58,7 +58,7 @@ extern "C" { // For ArrayPrivate and DictionaryPrivate static_assert(sizeof(SafeRefCount) == sizeof(uint32_t)); -typedef Object *(*godotsharp_class_creation_func)(); +typedef Object *(*godotsharp_class_creation_func)(bool); bool godotsharp_dotnet_module_is_initialized() { return GDMono::get_singleton()->is_initialized(); diff --git a/modules/webrtc/webrtc_peer_connection.cpp b/modules/webrtc/webrtc_peer_connection.cpp index 0a50b677c463..69be873fcf3c 100644 --- a/modules/webrtc/webrtc_peer_connection.cpp +++ b/modules/webrtc/webrtc_peer_connection.cpp @@ -43,15 +43,20 @@ void WebRTCPeerConnection::set_default_extension(const StringName &p_extension) default_extension = StringName(p_extension, true); } -WebRTCPeerConnection *WebRTCPeerConnection::create() { +WebRTCPeerConnection *WebRTCPeerConnection::create(bool p_notify_postinitialize) { #ifdef WEB_ENABLED - return memnew(WebRTCPeerConnectionJS); + return static_cast(ClassDB::creator(p_notify_postinitialize)); #else if (default_extension == StringName()) { WARN_PRINT_ONCE("No default WebRTC extension configured."); - return memnew(WebRTCPeerConnectionExtension); + return static_cast(ClassDB::creator(p_notify_postinitialize)); + } + Object *obj = nullptr; + if (p_notify_postinitialize) { + obj = ClassDB::instantiate(default_extension); + } else { + obj = ClassDB::instantiate_without_postinitialization(default_extension); } - Object *obj = ClassDB::instantiate(default_extension); return Object::cast_to(obj); #endif } diff --git a/modules/webrtc/webrtc_peer_connection.h b/modules/webrtc/webrtc_peer_connection.h index 0f79c17519b3..33c95ccd0f71 100644 --- a/modules/webrtc/webrtc_peer_connection.h +++ b/modules/webrtc/webrtc_peer_connection.h @@ -85,7 +85,7 @@ class WebRTCPeerConnection : public RefCounted { virtual Error poll() = 0; virtual void close() = 0; - static WebRTCPeerConnection *create(); + static WebRTCPeerConnection *create(bool p_notify_postinitialize = true); WebRTCPeerConnection(); ~WebRTCPeerConnection(); diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index 38f15c82e549..fe0bc594e637 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -68,7 +68,7 @@ class EMWSPeer : public WebSocketPeer { String selected_protocol; String requested_url; - static WebSocketPeer *_create() { return memnew(EMWSPeer); } + static WebSocketPeer *_create(bool p_notify_postinitialize) { return static_cast(ClassDB::creator(p_notify_postinitialize)); } static void _esws_on_connect(void *obj, char *proto); static void _esws_on_message(void *obj, const uint8_t *p_data, int p_data_size, int p_is_string); static void _esws_on_error(void *obj); diff --git a/modules/websocket/websocket_peer.cpp b/modules/websocket/websocket_peer.cpp index 3c0d316bc9d2..95a1a238e95a 100644 --- a/modules/websocket/websocket_peer.cpp +++ b/modules/websocket/websocket_peer.cpp @@ -30,7 +30,7 @@ #include "websocket_peer.h" -WebSocketPeer *(*WebSocketPeer::_create)() = nullptr; +WebSocketPeer *(*WebSocketPeer::_create)(bool p_notify_postinitialize) = nullptr; WebSocketPeer::WebSocketPeer() { } diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index 3110e87071c2..ef0197cf6c96 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -59,7 +59,7 @@ class WebSocketPeer : public PacketPeer { virtual Error _send_bind(const PackedByteArray &p_data, WriteMode p_mode = WRITE_MODE_BINARY); protected: - static WebSocketPeer *(*_create)(); + static WebSocketPeer *(*_create)(bool p_notify_postinitialize); static void _bind_methods(); @@ -74,11 +74,11 @@ class WebSocketPeer : public PacketPeer { int max_queued_packets = 2048; public: - static WebSocketPeer *create() { + static WebSocketPeer *create(bool p_notify_postinitialize = true) { if (!_create) { return nullptr; } - return _create(); + return _create(p_notify_postinitialize); } virtual Error connect_to_url(const String &p_url, Ref p_options = Ref()) = 0; diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index bf9f5c852732..fb01da7ce298 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -49,7 +49,7 @@ class WSLPeer : public WebSocketPeer { private: static CryptoCore::RandomGenerator *_static_rng; - static WebSocketPeer *_create() { return memnew(WSLPeer); } + static WebSocketPeer *_create(bool p_notify_postinitialize) { return static_cast(ClassDB::creator(p_notify_postinitialize)); } // Callbacks. static ssize_t _wsl_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, int flags, void *user_data); diff --git a/platform/web/http_client_web.cpp b/platform/web/http_client_web.cpp index ea9226a5a48b..80257dc2954f 100644 --- a/platform/web/http_client_web.cpp +++ b/platform/web/http_client_web.cpp @@ -266,11 +266,11 @@ Error HTTPClientWeb::poll() { return OK; } -HTTPClient *HTTPClientWeb::_create_func() { - return memnew(HTTPClientWeb); +HTTPClient *HTTPClientWeb::_create_func(bool p_notify_postinitialize) { + return static_cast(ClassDB::creator(p_notify_postinitialize)); } -HTTPClient *(*HTTPClient::_create)() = HTTPClientWeb::_create_func; +HTTPClient *(*HTTPClient::_create)(bool p_notify_postinitialize) = HTTPClientWeb::_create_func; HTTPClientWeb::HTTPClientWeb() { } diff --git a/platform/web/http_client_web.h b/platform/web/http_client_web.h index 4d3c457a7d06..f696c5a5b0ad 100644 --- a/platform/web/http_client_web.h +++ b/platform/web/http_client_web.h @@ -81,7 +81,7 @@ class HTTPClientWeb : public HTTPClient { static void _parse_headers(int p_len, const char **p_headers, void *p_ref); public: - static HTTPClient *_create_func(); + static HTTPClient *_create_func(bool p_notify_postinitialize); Error request(Method p_method, const String &p_url, const Vector &p_headers, const uint8_t *p_body, int p_body_size) override;