@@ -196,9 +196,9 @@ GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugi
196196
197197} // namespace internal
198198
199- GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr ;
200- GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr ;
201- GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE ;
199+ bool GDExtensionBinding::api_initialized = false ;
200+ int GDExtensionBinding::level_initialized[MODULE_INITIALIZATION_LEVEL_MAX] = { 0 } ;
201+ GDExtensionBinding::InitDataList GDExtensionBinding::initdata ;
202202
203203#define ERR_PRINT_EARLY (m_msg ) \
204204internal::gdextension_interface_print_error (m_msg, FUNCTION_STR, __FILE__, __LINE__, false )
@@ -225,7 +225,20 @@ typedef struct {
225225GDExtensionInterfacePrintErrorWithMessage print_error_with_message;
226226} LegacyGDExtensionInterface;
227227
228- GDExtensionBool GDExtensionBinding::init (GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
228+ GDExtensionBool GDExtensionBinding::init (GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization) {
229+ if (!p_init_data || !p_init_data->init_callback ) {
230+ ERR_FAIL_V_MSG (false , " Initialization callback must be defined." );
231+ }
232+
233+ if (api_initialized) {
234+ r_initialization->initialize = initialize_level;
235+ r_initialization->deinitialize = deinitialize_level;
236+ r_initialization->userdata = p_init_data;
237+ r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level ;
238+
239+ return true ;
240+ }
241+
229242// Make sure we weren't passed the legacy struct.
230243uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address;
231244if (raw_interface[0 ] == 4 && raw_interface[1 ] == 0 ) {
@@ -415,59 +428,96 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
415428
416429r_initialization->initialize = initialize_level;
417430r_initialization->deinitialize = deinitialize_level;
418- r_initialization->minimum_initialization_level = minimum_initialization_level;
419-
420- ERR_FAIL_NULL_V_MSG (init_callback, false , " Initialization callback must be defined." );
431+ r_initialization->userdata = p_init_data;
432+ r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level ;
421433
422434Variant::init_bindings ();
423435godot::internal::register_engine_classes ();
424436
437+ api_initialized = true ;
425438return true ;
426439}
427440
428441#undef LOAD_PROC_ADDRESS
429442#undef ERR_PRINT_EARLY
430443
431- void GDExtensionBinding::initialize_level (void *userdata, GDExtensionInitializationLevel p_level) {
444+ void GDExtensionBinding::initialize_level (void *p_userdata, GDExtensionInitializationLevel p_level) {
445+ ERR_FAIL_COND (static_cast <ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX);
432446ClassDB::current_level = p_level;
433447
434- if (init_callback) {
435- init_callback (static_cast <ModuleInitializationLevel>(p_level));
448+ InitData *init_data = static_cast <InitData *>(p_userdata);
449+ if (init_data && init_data->init_callback ) {
450+ init_data->init_callback (static_cast <ModuleInitializationLevel>(p_level));
436451}
437452
438- ClassDB::initialize (p_level);
453+ if (level_initialized[p_level] == 0 ) {
454+ ClassDB::initialize (p_level);
455+ }
456+ level_initialized[p_level]++;
439457}
440458
441- void GDExtensionBinding::deinitialize_level (void *userdata, GDExtensionInitializationLevel p_level) {
459+ void GDExtensionBinding::deinitialize_level (void *p_userdata, GDExtensionInitializationLevel p_level) {
460+ ERR_FAIL_COND (static_cast <ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX);
442461ClassDB::current_level = p_level;
443462
444- if (terminate_callback) {
445- terminate_callback (static_cast <ModuleInitializationLevel>(p_level));
463+ InitData *init_data = static_cast <InitData *>(p_userdata);
464+ if (init_data && init_data->terminate_callback ) {
465+ init_data->terminate_callback (static_cast <ModuleInitializationLevel>(p_level));
466+ }
467+
468+ level_initialized[p_level]--;
469+ if (level_initialized[p_level] == 0 ) {
470+ EditorPlugins::deinitialize (p_level);
471+ ClassDB::deinitialize (p_level);
472+ }
473+ }
474+
475+ void GDExtensionBinding::InitDataList::add (InitData *p_data) {
476+ if (data_count == data_capacity) {
477+ void *new_ptr = realloc (data, sizeof (InitData *) * (data_capacity + 32 ));
478+ if (new_ptr) {
479+ data = (InitData **)(new_ptr);
480+ data_capacity += 32 ;
481+ } else {
482+ ERR_FAIL_MSG (" Unable to allocate memory for extension callbacks." );
483+ }
446484}
485+ data[data_count++] = p_data;
486+ }
447487
448- EditorPlugins::deinitialize (p_level);
449- ClassDB::deinitialize (p_level);
488+ GDExtensionBinding::InitDataList::~InitDataList () {
489+ for (int i = 0 ; i < data_count; i++) {
490+ if (data[i]) {
491+ delete data[i];
492+ }
493+ }
494+ if (data) {
495+ free (data);
496+ }
450497}
498+
451499GDExtensionBinding::InitObject::InitObject (GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
452500get_proc_address = p_get_proc_address;
453501library = p_library;
454502initialization = r_initialization;
503+ init_data = new InitData ();
504+ GDExtensionBinding::initdata.add (init_data);
455505}
456506
457507void GDExtensionBinding::InitObject::register_initializer (Callback p_init) const {
458- GDExtensionBinding:: init_callback = p_init;
508+ init_data-> init_callback = p_init;
459509}
460510
461511void GDExtensionBinding::InitObject::register_terminator (Callback p_terminate) const {
462- GDExtensionBinding:: terminate_callback = p_terminate;
512+ init_data-> terminate_callback = p_terminate;
463513}
464514
465515void GDExtensionBinding::InitObject::set_minimum_library_initialization_level (ModuleInitializationLevel p_level) const {
466- GDExtensionBinding:: minimum_initialization_level = static_cast <GDExtensionInitializationLevel>(p_level);
516+ init_data-> minimum_initialization_level = static_cast <GDExtensionInitializationLevel>(p_level);
467517}
468518
469519GDExtensionBool GDExtensionBinding::InitObject::init () const {
470- return GDExtensionBinding::init (get_proc_address, library, initialization);
520+ return GDExtensionBinding::init (get_proc_address, library, init_data, initialization);
471521}
472522
473523} // namespace godot
0 commit comments