How to define `_input` method in GDNative C++?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Carl Marqs

I was able to receive _ready and _process in my GDNative C++ class already and was trying to capture InputEvent in _input. The method is declared as:

void Lantern::_input(godot::Ref<godot::InputEvent> event)

Compiler:

g++ -o game/scripts/Lantern.os -c -std=c++17 -fPIC -g -O3 -fPIC -I. -Igodot-cpp/godot_headers -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Igame/scripts game/scripts/Lantern.cpp
In file included from godot-cpp/include/core/Godot.hpp:12,
                 from game/scripts/Lantern.h:4,
                 from game/scripts/Lantern.cpp:1:
godot-cpp/include/core/Ref.hpp: In instantiation of 'godot::Ref<T>::Ref(const godot::Variant&) [with T = godot::InputEvent]':
godot-cpp/include/core/Godot.hpp:78:10:   required from 'static T godot::_ArgCast<T>::_arg_cast(godot::Variant) [with T = godot::Ref<godot::InputEvent>]'
godot-cpp/include/core/Godot.hpp:193:36:   required from 'void godot::_WrappedMethod<T, void, As ...>::apply(godot::Variant*, T*, godot::Variant**, godot::__Sequence<I ...>) [with int ...I = {0}; T = godot::Lantern; As = {godot::Ref<godot::InputEvent>}]'
godot-cpp/include/core/Godot.hpp:208:2:   required from 'godot_variant godot::__wrapped_method(godot_object*, void*, void*, int, godot_variant**) [with T = godot::Lantern; R = void; As = {godot::Ref<godot::InputEvent>}; godot_object = void]'
godot-cpp/include/core/Godot.hpp:223:9:   required from 'godot_variant (* godot::___get_wrapper_function(R (T::*)(As ...)))(godot_object*, void*, void*, int, godot_variant**) [with T = godot::Lantern; R = void; As = {godot::Ref<godot::InputEvent>}; godot::__godot_wrapper_method = godot_variant (*)(void*, void*, void*, int, godot_variant**); godot_object = void]'
godot-cpp/include/core/Godot.hpp:241:65:   required from 'void godot::register_method(const char*, M, godot_method_rpc_mode) [with M = void (godot::Lantern::*)(godot::Ref<godot::InputEvent>)]'
game/scripts/Lantern.cpp:6:45:   required from here
godot-cpp/include/core/Ref.hpp:159:56: error: incomplete type 'godot::InputEvent' used in nested name specifier
  159 |   Reference *refb = (Reference *)T::___get_from_variant(p_variant);
      |                                  ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
godot-cpp/include/core/Ref.hpp: In instantiation of 'void godot::Ref<T>::unref() [with T = godot::InputEvent]':
godot-cpp/include/core/Ref.hpp:200:3:   required from 'godot::Ref<T>::~Ref() [with T = godot::InputEvent]'
godot-cpp/include/core/Godot.hpp:193:36:   required from 'void godot::_WrappedMethod<T, void, As ...>::apply(godot::Variant*, T*, godot::Variant**, godot::__Sequence<I ...>) [with int ...I = {0}; T = godot::Lantern; As = {godot::Ref<godot::InputEvent>}]'
godot-cpp/include/core/Godot.hpp:208:2:   required from 'godot_variant godot::__wrapped_method(godot_object*, void*, void*, int, godot_variant**) [with T = godot::Lantern; R = void; As = {godot::Ref<godot::InputEvent>}; godot_object = void]'
godot-cpp/include/core/Godot.hpp:223:9:   required from 'godot_variant (* godot::___get_wrapper_function(R (T::*)(As ...)))(godot_object*, void*, void*, int, godot_variant**) [with T = godot::Lantern; R = void; As = {godot::Ref<godot::InputEvent>}; godot::__godot_wrapper_method = godot_variant (*)(void*, void*, void*, int, godot_variant**); godot_object = void]'
godot-cpp/include/core/Godot.hpp:241:65:   required from 'void godot::register_method(const char*, M, godot_method_rpc_mode) [with M = void (godot::Lantern::*)(godot::Ref<godot::InputEvent>)]'
game/scripts/Lantern.cpp:6:45:   required from here
godot-cpp/include/core/Ref.hpp:180:31: error: invalid use of incomplete type 'class godot::InputEvent'
  180 |   if (reference && reference->unreference()) {
      |                    ~~~~~~~~~~~^~~~~~~~~~~
In file included from godot-cpp/include/gen/CanvasItem.hpp:11,
                 from godot-cpp/include/gen/Node2D.hpp:11,
                 from godot-cpp/include/gen/Light2D.hpp:12,
                 from game/scripts/Lantern.h:5,
                 from game/scripts/Lantern.cpp:1:
godot-cpp/include/gen/Node.hpp:15:7: note: forward declaration of 'class godot::InputEvent'
   15 | class InputEvent;
      |       ^~~~~~~~~~
In file included from godot-cpp/include/core/Godot.hpp:12,
                 from game/scripts/Lantern.h:4,
                 from game/scripts/Lantern.cpp:1:
godot-cpp/include/core/Ref.hpp:183:15: error: invalid use of incomplete type 'class godot::InputEvent'
  183 |    reference->free();
      |    ~~~~~~~~~~~^~~~
In file included from godot-cpp/include/gen/CanvasItem.hpp:11,
                 from godot-cpp/include/gen/Node2D.hpp:11,
                 from godot-cpp/include/gen/Light2D.hpp:12,
                 from game/scripts/Lantern.h:5,
                 from game/scripts/Lantern.cpp:1:
godot-cpp/include/gen/Node.hpp:15:7: note: forward declaration of 'class godot::InputEvent'
   15 | class InputEvent;
      |       ^~~~~~~~~~

So, what is the correct way to define _input method inside GDNative C++?

Have you tried with

_input(InputEvent *event);

?

gmaps | 2019-11-04 08:17

Yep, it was my first attempt.

Compiler:

g++ -o game/scripts/Lantern.os -c -std=c++17 -fPIC -g -O3 -fPIC -I. -Igodot-cpp/godot_headers -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Igame/scripts game/scripts/Lantern.cpp
In file included from game/scripts/Lantern.h:4,
                 from game/scripts/Lantern.cpp:1:
godot-cpp/include/core/Godot.hpp: In instantiation of 'static T* godot::_ArgCast<T*>::_arg_cast(godot::Variant) [with T = godot::InputEvent]':
godot-cpp/include/core/Godot.hpp:193:36:   required from 'void godot::_WrappedMethod<T, void, As ...>::apply(godot::Variant*, T*, godot::Variant**, godot::__Sequence<I ...>) [with int ...I = {0}; T = godot::Lantern; As = {godot::InputEvent*}]'
godot-cpp/include/core/Godot.hpp:208:2:   required from 'godot_variant godot::__wrapped_method(godot_object*, void*, void*, int, godot_variant**) [with T = godot::Lantern; R = void; As = {godot::InputEvent*}; godot_object = void]'
godot-cpp/include/core/Godot.hpp:223:9:   required from 'godot_variant (* godot::___get_wrapper_function(R (T::*)(As ...)))(godot_object*, void*, void*, int, godot_variant**) [with T = godot::Lantern; R = void; As = {godot::InputEvent*}; godot::__godot_wrapper_method = godot_variant (*)(void*, void*, void*, int, godot_variant**); godot_object = void]'
godot-cpp/include/core/Godot.hpp:241:65:   required from 'void godot::register_method(const char*, M, godot_method_rpc_mode) [with M = void (godot::Lantern::*)(godot::InputEvent*)]'
game/scripts/Lantern.cpp:6:45:   required from here
godot-cpp/include/core/Godot.hpp:85:37: error: incomplete type 'godot::InputEvent' used in nested name specifier
   85 |   return (T *)T::___get_from_variant(a);
      |               ~~~~~~~~~~~~~~~~~~~~~~^~~
scons: *** [game/scripts/Lantern.os] Error 1
scons: building terminated because of errors.

Carl Marqs | 2019-11-04 20:16

:bust_in_silhouette: Reply From: Bengt Söderström

Use Variant:

void Lantern::_input(Variant event)
{
    Ref<InputEventJoypadButton> joy_btn = event;
    if (joy_btn->get_button_index() == GlobalConstants::JOY_SONY_TRIANGLE && 
        joy_btn->is_pressed())
        Godot::print("Pressed Triangle");
}

You can also call input events outside of _input(Variant event) using:

void Lantern::_process(float delta)
{    
    Input* input = Input::get_singleton();
    if (input->is_joy_button_pressed(0, GlobalConstants::JOY_SONY_X))
        Godot::print("Pressed X");
}