Compilation error in windows VSC++

Godot Version

4.3

Question

Hello all ,
i tring to compile simple method that getting argument simple object pointer
no matter what i do im getting compilation error
damage_data.h

#ifndef __DAMAGE_DATA__
#define __DAMAGE_DATA__

class DamageData
{
public:
	DamageData() = default;
	virtual ~DamageData() = default;
	int amount = 1;
};



#endif

health_manager.h

#ifndef HEALTH_MANAGER_H
#define HEALTH_MANAGER_H

#include <godot_cpp/classes/node3d.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/signal.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/variant/variant.hpp>
#include "damage_data.h"


using namespace godot;

class HealthManager : public Node3D {
    GDCLASS(HealthManager, Node3D)

 
public:
    HealthManager(){};
    virtual ~HealthManager() = default;

    virtual void _ready() override;

    void hurt(DamageData *damage_data);
    void heal(int amount);

    int get_max_health() const { return max_health; }
    void set_max_health(int value) { max_health = value; }

    int get_gib_at() const { return gib_at; }
    void set_gib_at(int value) { gib_at = value; }

    bool get_verbose() const { return verbose; }
    void set_verbose(bool value) { verbose = value; }

    void test_damage(){};

protected:
    static void _bind_methods();

private:
    int max_health = 100;
    int cur_health = 100;
    int gib_at = -10;
    bool verbose = false;

};

health_manager.cpp

#include "health_manager.h"

void HealthManager::_bind_methods() 
{

    // Signals
    ADD_SIGNAL(MethodInfo("died"));
    ADD_SIGNAL(MethodInfo("healed"));
    ADD_SIGNAL(MethodInfo("damaged"));
    ADD_SIGNAL(MethodInfo("gibbed"));
    ADD_SIGNAL(MethodInfo("health_changed", PropertyInfo(Variant::INT, "cur_health"), PropertyInfo(Variant::INT, "max_health")));
    // Properties
    ClassDB::bind_method(D_METHOD("get_max_health"), &HealthManager::get_max_health);
    ClassDB::bind_method(D_METHOD("set_max_health", "value"), &HealthManager::set_max_health);
    ADD_PROPERTY(PropertyInfo(Variant::INT, "max_health"), "set_max_health", "get_max_health");

    ClassDB::bind_method(D_METHOD("get_gib_at"), &HealthManager::get_gib_at);
    ClassDB::bind_method(D_METHOD("set_gib_at", "value"), &HealthManager::set_gib_at);
    ADD_PROPERTY(PropertyInfo(Variant::INT, "gib_at"), "set_gib_at", "get_gib_at");

    ClassDB::bind_method(D_METHOD("get_verbose"), &HealthManager::get_verbose);
    ClassDB::bind_method(D_METHOD("set_verbose", "value"), &HealthManager::set_verbose);
    ADD_PROPERTY(PropertyInfo(Variant::BOOL, "verbose"), "set_verbose", "get_verbose");

    // Methods
    ClassDB::bind_method(D_METHOD("hurt", "damage_data"), &HealthManager::hurt);
    ClassDB::bind_method(D_METHOD("heal", "amount"), &HealthManager::heal);

   
}

void HealthManager::_ready() {
    cur_health = max_health;
    emit_signal("health_changed", cur_health, max_health);

    if (verbose) {
        UtilityFunctions::print("Starting health: ", cur_health, "/", max_health);
    }
}

void HealthManager::hurt(DamageData *damage_data) {
    
    if (cur_health <= 0) {
        return;
    }

    int damage_amount = damage_data->amount;
    cur_health -= damage_amount;

    if (cur_health <= gib_at) {
        emit_signal("gibbed");
    }

    if (cur_health <= 0) {
        emit_signal("died");
    }
    else {
        emit_signal("damaged");
    }

    emit_signal("health_changed", cur_health, max_health);

    if (verbose) {
        UtilityFunctions::print("Damaged for ", damage_amount, ", health: ", cur_health, "/", max_health);
    }
}

void HealthManager::heal(int amount) {
    if (cur_health <= 0) {
        return;
    }

    cur_health = Math::clamp(cur_health + amount, 0, max_health);
    emit_signal("healed");
    emit_signal("health_changed", cur_health, max_health);

    if (verbose) {
        UtilityFunctions::print("Healed for ", amount, ", health: ", cur_health, "/", max_health);
    }
}

//void HealthManager::test_damage()
//{
//    DamageData* d = new DamageData();
//    d->amount = 30;
//    hurt(d);
//}

and i register it like this

#include "register_types.h"

#include "gdexample.h"
#include "health_manager.h"
#include "custom_mover.h"
#include "player.h"

#include <gdextension_interface.h>
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/godot.hpp>

using namespace godot;

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

	GDREGISTER_CLASS(GDExample);
	GDREGISTER_CLASS(HealthManager);
	GDREGISTER_RUNTIME_CLASS(CustomMover);
	GDREGISTER_RUNTIME_CLASS(Player);

}

i keep getting this error :

scons: `C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\bin\libgodot-cpp.windows.template_debug.x86_64.lib' is up to date.
Compiling src\health_manager.cpp ...
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_ptrcall.hpp(172): error C2338: static_assert failed: 'Cannot encode non-Object value as an Object'
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(193): note: see reference to class template instantiation 'godot::PtrToArg<DamageData *>' being compiled
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(213): note: see reference to function template instantiation 'void godot::call_with_ptr_args_helper<T,DamageData*,0>(T *,void (__cdecl HealthManager::* )(DamageData *),const GDExtensionConstTypePtr *,IndexSequence<0>)' being compiled
        with
        [
            T=HealthManager
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(327): note: see reference to function template instantiation 'void godot::call_with_ptr_args<T,DamageData*>(T *,void (__cdecl HealthManager::* )(DamageData *),const GDExtensionConstTypePtr *,void *)' being compiled
        with
        [
            T=HealthManager
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(327): note: while compiling class template member function 'void godot::MethodBindT<T,DamageData *>::ptrcall(GDExtensionClassInstancePtr,const GDExtensionConstTypePtr *,GDExtensionTypePtr) const'
        with
        [
            T=HealthManager
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(343): note: see reference to class template instantiation 'godot::MethodBindT<T,DamageData *>' being compiled
        with
        [
            T=HealthManager
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/class_db.hpp(298): note: see reference to function template instantiation 'godot::MethodBind *godot::create_method_bind<HealthManager,DamageData*>(void (__cdecl HealthManager::* )(DamageData *))' being compiled
src\health_manager.cpp(26): note: see reference to function template instantiation 'godot::MethodBind *godot::ClassDB::bind_method<godot::MethodDefinition,void(__cdecl HealthManager::* )(DamageData *),>(N,M)' being compiled
        with
        [
            N=godot::MethodDefinition,
            M=void (__cdecl HealthManager::* )(DamageData *)
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(521): error C2027: use of undefined type 'godot::GetTypeInfo<Q,void>'
        with
        [
            Q=DamageData *
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(521): note: see declaration of 'godot::GetTypeInfo<Q,void>'
        with
        [
            Q=DamageData *
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(527): note: see reference to function template instantiation 'void godot::call_get_argument_metadata_helper<DamageData*>(int,int &,GDExtensionClassMethodArgumentMetadata &)' being compiled
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(315): note: see reference to function template instantiation 'GDExtensionClassMethodArgumentMetadata godot::call_get_argument_metadata<DamageData*>(int)' being compiled
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(315): note: while compiling class template member function 'GDExtensionClassMethodArgumentMetadata godot::MethodBindT<T,DamageData *>::get_argument_metadata(int) const'
        with
        [
            T=HealthManager
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(521): error C2065: 'METADATA': undeclared identifier
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(503): error C2027: use of undefined type 'godot::GetTypeInfo<Q,void>'
        with
        [
            Q=DamageData *
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(521): note: see declaration of 'godot::GetTypeInfo<Q,void>'
        with
        [
            Q=DamageData *
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(509): note: see reference to function template instantiation 'void godot::call_get_argument_type_info_helper<DamageData*>(int,int &,godot::PropertyInfo &)' being compiled
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(301): note: see reference to function template instantiation 'void godot::call_get_argument_type_info<DamageData*>(int,godot::PropertyInfo &)' being compiled
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(301): note: while compiling class template member function 'godot::PropertyInfo godot::MethodBindT<T,DamageData *>::gen_argument_type_info(int) const'
        with
        [
            T=HealthManager
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(503): error C3861: 'get_class_info': identifier not found
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(483): error C2027: use of undefined type 'godot::GetTypeInfo<Q,void>'
        with
        [
            Q=DamageData *
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(521): note: see declaration of 'godot::GetTypeInfo<Q,void>'
        with
        [
            Q=DamageData *
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(489): note: see reference to function template instantiation 'void godot::call_get_argument_type_helper<DamageData*>(int,int &,GDExtensionVariantType &)' being compiled
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(293): note: see reference to function template instantiation 'GDExtensionVariantType godot::call_get_argument_type<DamageData*>(int)' being compiled
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/method_bind.hpp(293): note: while compiling class template member function 'GDExtensionVariantType godot::MethodBindT<T,DamageData *>::gen_argument_type(int) const'
        with
        [
            T=HealthManager
        ]
C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\include\godot_cpp/core/binder_common.hpp(483): error C2065: 'VARIANT_TYPE': undeclared identifier
scons: *** [obj\health_manager.obj] Error 2
scons: building terminated because of errors.

what am i missing here ?

Godot cannot “read” a DamageData.

You must only use what Godot knows how to use, which are the variant types: Object, Vector2, String, AABB, int, etc.

The culprit looks to be the HealthManager::hurt(DamageData*) method.

Potential fix: have DamageData inherit from RefCounted or Object.
Alternative fix: Store DamageData internally. Expose hurt(int amount) method with parameters to build damage data.

Thanks!
Really? I can’t just pass C/C++ standard object pointers? Do I need to wrap them?
Could you point me to some reading material or something?
Beside the doc : RefCounted — Godot Engine (stable) documentation in English

I remember doing this in a previous version.
By the way, I don’t want to expose anything to GDScript—just keep it all in C++. Does that matter?

Yes, when you bind methods, in other words expose a method to Godot, Godot has to know how to handle it. It needs a common terminology so it can pass this information around the engine, to C#, to modules, or to other GDExtensions. That is a design decision. Remember to only use the Godot Variant types when binding an interface to Godot.

In that case, you don’t have to bind anything and can use any C++ data type or feature you would like.

It’s only when you are interacting with godot.

ok i see , so if it exposed , can i wire the editor timer timeout to this method ?

Yes. Connecting a signal interacts with Godot and requires the exposed method to only use data types known to Godot.