Virtual methods in gdextension

Godot version : Godot_v4.4.1-stable_linux.x86_64

Context:

I am trying to make a gdextension implementation of behaviour trees. So I use classes, inheritance, and virtual functions.

Problem:

My classes inheriting from other classes with virtual functions are not detected by the GDScript editor. However, their base classes are registered correctly. Sometimes the output console is empty, sometimes I get these errors :

  ERROR: Extension runtime class 'GdrBtNodeNative' cannot descend from 'GdrBaseBtNode' which isn't also a runtime class.
  ERROR: Extension runtime class 'GdrBehaviourSelector' cannot descend from 'GdrBaseNativeBehaviour' which isn't also a runtime class.

I cannot find any documentation on the subject and the extension won’t compile if I try to register the base classes as anything other than abstract

Code example:

Here are the important parts of some minimalistic code that reproduces the error. It compiles, and the GDScript editor knows BaseClass but not ChildClass:

test.hh


# ifndef TEST_H
# define TEST_H

# include <godot_cpp/core/binder_common.hpp>
# include <godot_cpp/core/class_db.hpp>
# include <godot_cpp/classes/object.hpp>


using namespace godot;

namespace custom
{
	
    class BaseClass : public Object
    {

        GDCLASS(BaseClass, Object);

        public :

        static void _bind_methods();

        void RealMethod();

        virtual void VirtualMethod() = 0;
    };


    class ChildClass : public BaseClass
    {
        GDCLASS(ChildClass, BaseClass)

        public :

        static void _bind_methods();

        void AnotherRealMethod();

        void VirtualMethod() override;
    };

}



# endif // TEST_H

register_classes.cpp

using namespace godot;
using namespace custom;

void initialize_module(ModuleInitializationLevel p_level)
{
	if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE)
    {
		return;
	}

	GDREGISTER_ABSTRACT_CLASS(BaseClass);
    GDREGISTER_RUNTIME_CLASS(ChildClass);
}

void uninitialize_module(ModuleInitializationLevel p_level)
{
	if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE)
    {
		return;
	}
}

extern "C" {

    // Initialization.
    GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
    {
        godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);

        init_obj.register_initializer(initialize_module);
        init_obj.register_terminator(uninitialize_module);
        init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);

        return init_obj.init();
    }
}
1 Like

There seems to be a todo in the code on this.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.