Issue when compiling a C++ node when returning an array

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

Hi there everyone,

I have an issue while trying to compile a module written in C++ which has function that returns an array, or better, a pointer to an array. It appears that GetTypeInfo gets grumpy because of “incomplete type 'GetTypeInfo<int , void>’ used in nested name specifier”, see below.

I have downloaded the latest Godot source files from GitLab and coded the files below in the “godot\modules” folder.

I don’t have issues compiling while returning some other types, like int.

What am I missing, please?

Here’s the code.

simpleNode.cpp

  #include "simpleNode.h"

SimpleNode::SimpleNode(){}

int arrayToReturn[2];

//Bind all your methods used in this class
void SimpleNode::_bind_methods(){
  ClassDB::bind_method(D_METHOD("retArray"), &SimpleNode::retArray);
}


//Custom Functions
int * SimpleNode::retArray() {
  return arrayToReturn;
}

simpleNode.h

//insert the Headername here
#ifndef SIMPLENODE_H
#define SIMPLENODE_H

#include "scene/main/node.h"
#include <vector>


class SimpleNode : public Node {
	GDCLASS(SimpleNode, Node);

protected:
  static void _bind_methods();

public:
  SimpleNode();
  // Declares type returned by retArray as pointer
  int * retArray();

};

#endif

register_types.h

void register_simple_types();
void unregister_simple_types();

/*
	void register_MODULNAME_types();
	void unregister_MODULNAME_types();

	MODULNAME ->> insert the name of your module
*/

register_types.cpp

#include "register_types.h"
#include "core/class_db.h"
#include "simpleNode.h"

void register_simple_types(){
	ClassDB::register_class<SimpleNode>();
}

void unregister_simple_types() {
}

With this simple premise I have however this bunch of error messages when I try to compile with Scons the source code.

In file included from ./core/method_bind.h:407,
                 from ./core/class_db.h:34,
                 from ./scene/main/node.h:34,
                 from modules/simple/simpleNode.h:5,
                 from modules/simple/simpleNode.cpp:1:
./core/method_bind.gen.inc: In instantiation of 'PropertyInfo MethodBind0R<R>::_gen_argument_type_info(int) const [with R = int*]':
./core/method_bind.gen.inc:203:23:   required from here
./core/method_bind.gen.inc:204:60: error: incomplete type 'GetTypeInfo<int*, void>' used in nested name specifier
   if (p_argument==-1) return GetTypeInfo<R>::get_class_info();
                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
./core/method_bind.gen.inc: In instantiation of 'GodotTypeInfo::Metadata MethodBind0R<R>::get_argument_meta(int) const [with R = int*]':
./core/method_bind.gen.inc:191:34:   required from here
./core/method_bind.gen.inc:192:41: error: incomplete type 'GetTypeInfo<int*, void>' used in nested name specifier
   if (p_arg==-1) return GetTypeInfo<R>::METADATA;
                                         ^~~~~~~~
./core/method_bind.gen.inc: In instantiation of 'Variant::Type MethodBind0R<R>::_get_argument_type(int) const [with R = int*]':
./core/method_bind.gen.inc:190:69:   required from 'Variant::Type MethodBind0R<R>::_gen_argument_type(int) const [with R = int*]'
./core/method_bind.gen.inc:190:24:   required from here
./core/method_bind.gen.inc:198:30: error: incomplete type 'GetTypeInfo<int*, void>' used in nested name specifier
   if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
scons: *** [modules/simple/simpleNode.x11.tools.64.o] Error 1
scons: building terminated because of errors.
The terminal process "/bin/bash '-c', 'scons -j8'" terminated with exit code: 2.

Some more info on my system:

clang version 7.0.1-8+deb10u2 (tags/RELEASE_701/final)
gcc version 8.3.0 (Debian 8.3.0-6) 
Target: x86_64-pc-linux-gnu

This is my first query, so please forgive my several inaccuracies that I might have overlooked.

Thank you for your help!

the BusSeatProgrammer

:bust_in_silhouette: Reply From: willnationsdev

int arrayToReturn[2]; //Custom Functions int * SimpleNode::retArray() { return arrayToReturn; } //Bind all your methods used in this class void SimpleNode::_bind_methods() { ClassDB::bind_method(D_METHOD("retArray"), &SimpleNode::retArray); }

This is the problem. See the official development docs on Variant.

Any point at which the C++ code starts interacting with the Godot runtime is a place where you might have to start wrapping data inside Variant objects.

Any code where the language is passing information back to Godot Engine needs to have that code returned as a Variant-compatible data type, i.e. something that can implicitly or directly cast to Variant. This is why int works, but int[] and int* do not. To return an Array of values, you need either PoolIntArray (PackedIntArray in Godot 4.0) or an Array. All values inside of an Array are also Variant.

If your retArray method were to return one of those types instead, then the ClassDB::bind_method call would work.

For a list of Variant-compatible data types, see the @GlobalScope documentation on the Variant.Type enum.

Thanks you very much WillNationsDev!

Your reply really helped to get my head around the interaction between Godot and CPP.
Thank you!

BusSeatProgrammer | 2021-05-11 07:25

:bust_in_silhouette: Reply From: BusSeatProgrammer

As pointed out by WillNationsDev below, every time Godot has to interact with a CPP variable then the latter has to be wrapped in a Variant.

The simpleNode cpp example can be rewritten: first a CPP array and a Godot array are specified, then some operations are performed over the CPP array and in the end its content is copied into the Godot array.

simpleNode.cpp

#include "simpleNode.h"

SimpleNode::SimpleNode(){}

// Array kk;

//Bind all your methods used in this class
void SimpleNode::_bind_methods(){
  ClassDB::bind_method(D_METHOD("retArray"), &SimpleNode::retArray);
}


//Custom Functions
Array SimpleNode::retArray() {
  
  // Declares Godot array
  Array arrGdt;

  // Declares CPP array
  int arrCpp [3];

  arrCpp[0] = 1;
  arrCpp[1] = 2;
  arrCpp[2] = arrCpp[0] + arrCpp[1];
  
  // Copy Cpp array content into Godot array
  for (int element: arrCpp) {
    arrGdt.append(element);
  }

  // Return Godot array
  return arrGdt;
}

The header file needs to be modified as well.

simpleNode.h

//insert the Headername here
#ifndef SIMPLENODE_H
#define SIMPLENODE_H

#include "scene/main/node.h"


class SimpleNode : public Node {
	GDCLASS(SimpleNode, Node);

protected:
  static void _bind_methods();

public:
  SimpleNode();

  // Here the function is  declared to return a Godot array
  Array retArray();

};

#endif