Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions include/godot_cpp/classes/wrapped.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void free_c_property_list(GDExtensionPropertyInfo *plist);

typedef void (*EngineClassRegistrationCallback)();
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback);
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks, void (*p_destruct_class_static)());
void register_engine_classes();

template <typename T>
Expand All @@ -167,7 +167,7 @@ struct EngineClassRegistration {
}

static void callback() {
register_engine_class(T::get_class_static(), &T::_gde_binding_callbacks);
register_engine_class(T::get_class_static(), &T::_gde_binding_callbacks, T::destruct_class_static);
}
};

Expand Down Expand Up @@ -253,7 +253,16 @@ public:
} \
\
static const ::godot::StringName &get_class_static() { \
static const ::godot::StringName string_name = ::godot::StringName(U## #m_class); \
return get_class_static_nonconst(); \
} \
\
static void destruct_class_static() { \
::godot::StringName &class_static = get_class_static_nonconst(); \
class_static = StringName(); \
} \
\
static ::godot::StringName &get_class_static_nonconst() { \
static ::godot::StringName string_name = ::godot::StringName(U## #m_class); \
return string_name; \
} \
\
Expand Down Expand Up @@ -466,7 +475,16 @@ public:
static void initialize_class() {} \
\
static const ::godot::StringName &get_class_static() { \
static const ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return get_class_static_nonconst(); \
} \
\
static void destruct_class_static() { \
::godot::StringName &class_static = get_class_static_nonconst(); \
class_static = StringName(); \
} \
\
static ::godot::StringName &get_class_static_nonconst() { \
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return string_name; \
} \
\
Expand Down
5 changes: 4 additions & 1 deletion include/godot_cpp/core/class_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class ClassDB {
// This may only contain custom classes, not Godot classes
static HashMap<StringName, ClassInfo> classes;
static AHashMap<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
static std::set<void (*)()> instance_binding_destruct_class_static_callbacks;
// Used to remember the custom class registration order.
static LocalVector<StringName> class_register_order;
static AHashMap<StringName, Object *> engine_singletons;
Expand Down Expand Up @@ -161,8 +162,9 @@ class ClassDB {
template <typename T>
static void register_runtime_class();

_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks, void (*p_destruct_class_static)()) {
instance_binding_callbacks[p_name] = p_callbacks;
instance_binding_destruct_class_static_callbacks.insert(p_destruct_class_static);
}

static void _editor_get_classes_used_callback(GDExtensionTypePtr p_packed_string_array);
Expand Down Expand Up @@ -240,6 +242,7 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
static_assert(!FunctionsAreSame<T::self_type::_bind_methods, T::parent_type::_bind_methods>::value, "Class must declare 'static void _bind_methods'.");
static_assert(!std::is_abstract_v<T> || is_abstract, "Class is abstract, please use GDREGISTER_ABSTRACT_CLASS.");
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
instance_binding_destruct_class_static_callbacks.insert(T::destruct_class_static);

// Register this class within our plugin
ClassInfo cl;
Expand Down
4 changes: 2 additions & 2 deletions src/classes/wrapped.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ void add_engine_class_registration_callback(EngineClassRegistrationCallback p_ca
get_engine_class_registration_callbacks().push_back(p_callback);
}

void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
ClassDB::_register_engine_class(p_name, p_callbacks);
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks, void (*p_destruct_class_static)()) {
ClassDB::_register_engine_class(p_name, p_callbacks, p_destruct_class_static);
}

void register_engine_classes() {
Expand Down
8 changes: 8 additions & 0 deletions src/core/class_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ namespace godot {

HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes;
AHashMap<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks;
std::set<void (*)()> ClassDB::instance_binding_destruct_class_static_callbacks;
LocalVector<StringName> ClassDB::class_register_order;
AHashMap<StringName, Object *> ClassDB::engine_singletons;
std::mutex ClassDB::engine_singletons_mutex;
Expand Down Expand Up @@ -458,6 +459,13 @@ void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
for (const Object *i : singleton_objects) {
::godot::gdextension_interface::object_free_instance_binding((*i)._owner, ::godot::gdextension_interface::token);
}

instance_binding_callbacks.clear();

for (void (*destruct_class_static)() : instance_binding_destruct_class_static_callbacks) {
destruct_class_static();
}
instance_binding_destruct_class_static_callbacks.clear();
}
}

Expand Down