Writing an add-on with GDExtension, I'm looking to return an array of custom types on Godot 4. My first thought was writing a type like godot::Vector<godot::Ref<MyStruct>>
, but I discovered that the compiler complains, as this new type is incompatible with godot::Variant
.
So, I would like to know how I'm supposed to fulfil the requirements imposed by godot-cpp
. Here the compiler error:
➜ scons
scons: Reading SConscript files ...
Auto-detected 12 CPU cores available for build parallelism. Using 11 cores by default. You can override it with the -j argument.
Building for architecture x86_64 on platform linux
scons: done reading SConscript files.
scons: Building targets ...
scons: `godot-cpp/bin/libgodot-cpp.linux.template_debug.x86_64.a' is up to date.
g++ -o godot/hand_ranking_evaluation.os -c -std=c++17 -fPIC -Wwrite-strings -m64 -march=x86-64 -O2 -fPIC -DLINUX_ENABLED -DUNIX_ENABLED -DDEBUG_ENABLED -DDEBUG_METHODS_ENABLED -DNDEBUG -Igodot-cpp/gdextension -Igodot-cpp/include -Igodot-cpp/gen/include -I/nix/store/5hch4vqzwan8ksab4pfpyrbb7wvvv3ad-cxxtest-4.4/include -I/nix/store/7nbh3b6hhjqjs3nfy529g38l85iv46i9-openssl-3.0.11-dev/include -Isrc -Iompeval/omp -Igodot godot/hand_ranking_evaluation.cpp
g++ -o godot/register_types.os -c -std=c++17 -fPIC -Wwrite-strings -m64 -march=x86-64 -O2 -fPIC -DLINUX_ENABLED -DUNIX_ENABLED -DDEBUG_ENABLED -DDEBUG_METHODS_ENABLED -DNDEBUG -Igodot-cpp/gdextension -Igodot-cpp/include -Igodot-cpp/gen/include -I/nix/store/5hch4vqzwan8ksab4pfpyrbb7wvvv3ad-cxxtest-4.4/include -I/nix/store/7nbh3b6hhjqjs3nfy529g38l85iv46i9-openssl-3.0.11-dev/include -Isrc -Iompeval/omp -Igodot godot/register_types.cpp
In file included from godot-cpp/include/godot_cpp/core/class_db.hpp:38,
from godot-cpp/gen/include/godot_cpp/classes/ref_counted.hpp:39,
from godot/../godot-cpp/include/godot_cpp/classes/ref.hpp:37,
from godot/poker.hpp:5,
from godot/hand_ranking_evaluation.cpp:1:
godot-cpp/include/godot_cpp/core/method_bind.hpp: In instantiation of 'GDExtensionVariantType godot::MethodBindTR<R, P>::gen_argument_type(int) const [with R = godot::Vector<godot::Ref<HandRankEvaluation> >; P = {}]':
godot-cpp/include/godot_cpp/core/method_bind.hpp:446:33: required from here
godot-cpp/include/godot_cpp/core/method_bind.hpp:450:71: error: incomplete type 'godot::GetTypeInfo<godot::Vector<godot::Ref<HandRankEvaluation> >, void>' used in nested name specifier
450 | return GDExtensionVariantType(GetTypeInfo<R>::VARIANT_TYPE);
| ^~~~~~~~~~~~
godot-cpp/include/godot_cpp/core/method_bind.hpp: In instantiation of 'godot::PropertyInfo godot::MethodBindTR<R, P>::gen_argument_type_info(int) const [with R = godot::Vector<godot::Ref<HandRankEvaluation> >; P = {}]':
godot-cpp/include/godot_cpp/core/method_bind.hpp:454:23: required from here
godot-cpp/include/godot_cpp/core/method_bind.hpp:460:62: error: incomplete type 'godot::GetTypeInfo<godot::Vector<godot::Ref<HandRankEvaluation> >, void>' used in nested name specifier
460 | return GetTypeInfo<R>::get_class_info();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
godot-cpp/include/godot_cpp/core/method_bind.hpp: In instantiation of 'GDExtensionClassMethodArgumentMetadata godot::MethodBindTR<R, P>::get_argument_metadata(int) const [with R = godot::Vector<godot::Ref<HandRankEvaluation> >; P = {}]':
godot-cpp/include/godot_cpp/core/method_bind.hpp:468:49: required from here
godot-cpp/include/godot_cpp/core/method_bind.hpp:472:48: error: incomplete type 'godot::GetTypeInfo<godot::Vector<godot::Ref<HandRankEvaluation> >, void>' used in nested name specifier
472 | return GetTypeInfo<R>::METADATA;
| ^~~~~~~~
In file included from godot-cpp/include/godot_cpp/core/method_bind.hpp:34:
godot-cpp/include/godot_cpp/core/binder_common.hpp: In instantiation of 'void godot::call_with_variant_args_ret_helper(T*, R (T::*)(P ...), const Variant**, Variant&, GDExtensionCallError&, IndexSequence<Is ...>) [with T = _gde_UnexistingClass; R = Vector<Ref<HandRankEvaluation> >; P = {}; long unsigned int ...Is = {}]':
godot-cpp/include/godot_cpp/core/binder_common.hpp:381:35: required from 'void godot::call_with_variant_args_ret_dv(T*, R (T::*)(P ...), const void* const*, int, Variant&, GDExtensionCallError&, const std::vector<Variant>&) [with T = _gde_UnexistingClass; R = Vector<Ref<HandRankEvaluation> >; P = {}; GDExtensionConstVariantPtr = const void*]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:481:32: required from 'godot::Variant godot::MethodBindTR<R, P>::call(GDExtensionClassInstancePtr, const void* const*, GDExtensionInt, GDExtensionCallError&) const [with R = godot::Vector<godot::Ref<HandRankEvaluation> >; P = {}; GDExtensionClassInstancePtr = void*; GDExtensionConstVariantPtr = const void*; GDExtensionInt = long int]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:476:18: required from here
godot-cpp/include/godot_cpp/core/binder_common.hpp:261:15: error: no match for 'operator=' (operand types are 'godot::Variant' and 'godot::Vector<godot::Ref<HandRankEvaluation> >')
261 | r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from godot-cpp/include/godot_cpp/variant/typed_array.hpp:35,
from godot-cpp/gen/include/godot_cpp/classes/object.hpp:41,
from godot/../godot-cpp/include/godot_cpp/classes/ref.hpp:36:
godot-cpp/include/godot_cpp/variant/variant.hpp:252:18: note: candidate: 'godot::Variant& godot::Variant::operator=(const godot::Variant&)'
252 | Variant &operator=(const Variant &other);
| ^~~~~~~~
godot-cpp/include/godot_cpp/variant/variant.hpp:252:43: note: no known conversion for argument 1 from 'godot::Vector<godot::Ref<HandRankEvaluation> >' to 'const godot::Variant&'
252 | Variant &operator=(const Variant &other);
| ~~~~~~~~~~~~~~~^~~~~
godot-cpp/include/godot_cpp/variant/variant.hpp:253:18: note: candidate: 'godot::Variant& godot::Variant::operator=(godot::Variant&&)'
253 | Variant &operator=(Variant &&other);
| ^~~~~~~~
godot-cpp/include/godot_cpp/variant/variant.hpp:253:38: note: no known conversion for argument 1 from 'godot::Vector<godot::Ref<HandRankEvaluation> >' to 'godot::Variant&&'
253 | Variant &operator=(Variant &&other);
| ~~~~~~~~~~^~~~~
godot-cpp/include/godot_cpp/core/binder_common.hpp: In instantiation of 'void godot::call_with_ptr_args_ret_helper(T*, R (T::*)(P ...), const void* const*, void*, IndexSequence<Is ...>) [with T = _gde_UnexistingClass; R = Vector<Ref<HandRankEvaluation> >; P = {}; long unsigned int ...Is = {}; GDExtensionConstTypePtr = const void*]':
godot-cpp/include/godot_cpp/core/binder_common.hpp:224:43: required from 'void godot::call_with_ptr_args(T*, R (T::*)(P ...), const void* const*, void*) [with T = _gde_UnexistingClass; R = Vector<Ref<HandRankEvaluation> >; P = {}; GDExtensionConstTypePtr = const void*]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:489:36: required from 'void godot::MethodBindTR<R, P>::ptrcall(GDExtensionClassInstancePtr, const void* const*, GDExtensionTypePtr) const [with R = godot::Vector<godot::Ref<HandRankEvaluation> >; P = {}; GDExtensionClassInstancePtr = void*; GDExtensionConstTypePtr = const void*; GDExtensionTypePtr = void*]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:485:15: required from here
godot-cpp/include/godot_cpp/core/binder_common.hpp:204:28: error: 'encode' is not a member of 'godot::PtrToArg<godot::Vector<godot::Ref<HandRankEvaluation> > >'
204 | PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
| ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
godot-cpp/include/godot_cpp/core/binder_common.hpp: In instantiation of 'void godot::call_get_argument_type_helper(int, int&, GDExtensionVariantType&) [with Q = Vector<Ref<HandRankEvaluation> >]':
godot-cpp/include/godot_cpp/core/binder_common.hpp:440:53: required from 'GDExtensionVariantType godot::call_get_argument_type(int) [with P = {Vector<Ref<HandRankEvaluation> >}]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:295:39: required from 'GDExtensionVariantType godot::MethodBindT<P>::gen_argument_type(int) const [with P = {godot::Vector<godot::Ref<HandRankEvaluation> >}]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:293:33: required from here
godot-cpp/include/godot_cpp/core/binder_common.hpp:429:63: error: incomplete type 'godot::GetTypeInfo<godot::Vector<godot::Ref<HandRankEvaluation> >, void>' used in nested name specifier
429 | type = GDExtensionVariantType(GetTypeInfo<Q>::VARIANT_TYPE);
| ^~~~~~~~~~~~
godot-cpp/include/godot_cpp/core/binder_common.hpp: In instantiation of 'void godot::call_get_argument_type_info_helper(int, int&, PropertyInfo&) [with Q = Vector<Ref<HandRankEvaluation> >]':
godot-cpp/include/godot_cpp/core/binder_common.hpp:459:58: required from 'void godot::call_get_argument_type_info(int, PropertyInfo&) [with P = {Vector<Ref<HandRankEvaluation> >}]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:304:37: required from 'godot::PropertyInfo godot::MethodBindT<P>::gen_argument_type_info(int) const [with P = {godot::Vector<godot::Ref<HandRankEvaluation> >}]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:301:23: required from here
godot-cpp/include/godot_cpp/core/binder_common.hpp:449:54: error: incomplete type 'godot::GetTypeInfo<godot::Vector<godot::Ref<HandRankEvaluation> >, void>' used in nested name specifier
449 | info = GetTypeInfo<Q>::get_class_info();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
godot-cpp/include/godot_cpp/core/binder_common.hpp: In instantiation of 'void godot::call_get_argument_metadata_helper(int, int&, GDExtensionClassMethodArgumentMetadata&) [with Q = Vector<Ref<HandRankEvaluation> >]':
godot-cpp/include/godot_cpp/core/binder_common.hpp:479:57: required from 'GDExtensionClassMethodArgumentMetadata godot::call_get_argument_metadata(int) [with P = {Vector<Ref<HandRankEvaluation> >}]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:316:42: required from 'GDExtensionClassMethodArgumentMetadata godot::MethodBindT<P>::get_argument_metadata(int) const [with P = {godot::Vector<godot::Ref<HandRankEvaluation> >}]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:315:49: required from here
godot-cpp/include/godot_cpp/core/binder_common.hpp:467:38: error: incomplete type 'godot::GetTypeInfo<godot::Vector<godot::Ref<HandRankEvaluation> >, void>' used in nested name specifier
467 | md = GetTypeInfo<Q>::METADATA;
| ^~~~~~~~
godot-cpp/include/godot_cpp/core/binder_common.hpp: In instantiation of 'void godot::call_with_ptr_args_helper(T*, void (T::*)(P ...), const void* const*, IndexSequence<Is ...>) [with T = _gde_UnexistingClass; P = {Vector<Ref<HandRankEvaluation> >}; long unsigned int ...Is = {0}; GDExtensionConstTypePtr = const void*]':
godot-cpp/include/godot_cpp/core/binder_common.hpp:214:36: required from 'void godot::call_with_ptr_args(T*, void (T::*)(P ...), const void* const*, void*) [with T = _gde_UnexistingClass; P = {Vector<Ref<HandRankEvaluation> >}; GDExtensionConstTypePtr = const void*]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:331:33: required from 'void godot::MethodBindT<P>::ptrcall(GDExtensionClassInstancePtr, const void* const*, GDExtensionTypePtr) const [with P = {godot::Vector<godot::Ref<HandRankEvaluation> >}; GDExtensionClassInstancePtr = void*; GDExtensionConstTypePtr = const void*; GDExtensionTypePtr = void*]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:327:15: required from here
godot-cpp/include/godot_cpp/core/binder_common.hpp:194:53: error: 'convert' is not a member of 'godot::PtrToArg<godot::Vector<godot::Ref<HandRankEvaluation> > >'
194 | (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
| ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
godot-cpp/include/godot_cpp/core/binder_common.hpp: In instantiation of 'static T godot::VariantCasterAndValidate<T>::cast(const godot::Variant**, uint32_t, GDExtensionCallError&) [with T = godot::Vector<godot::Ref<HandRankEvaluation> >; uint32_t = unsigned int]':
godot-cpp/include/godot_cpp/core/binder_common.hpp:237:59: required from 'void godot::call_with_variant_args_helper(T*, void (T::*)(P ...), const Variant**, GDExtensionCallError&, IndexSequence<Is ...>) [with T = _gde_UnexistingClass; P = {Vector<Ref<HandRankEvaluation> >}; long unsigned int ...Is = {0}]'
godot-cpp/include/godot_cpp/core/binder_common.hpp:311:31: required from 'void godot::call_with_variant_args_dv(T*, void (T::*)(P ...), const void* const*, int, GDExtensionCallError&, const std::vector<Variant>&) [with T = _gde_UnexistingClass; P = {Vector<Ref<HandRankEvaluation> >}; GDExtensionConstVariantPtr = const void*]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:323:28: required from 'godot::Variant godot::MethodBindT<P>::call(GDExtensionClassInstancePtr, const void* const*, GDExtensionInt, GDExtensionCallError&) const [with P = {godot::Vector<godot::Ref<HandRankEvaluation> >}; GDExtensionClassInstancePtr = void*; GDExtensionConstVariantPtr = const void*; GDExtensionInt = long int]'
godot-cpp/include/godot_cpp/core/method_bind.hpp:319:18: required from here
godot-cpp/include/godot_cpp/core/binder_common.hpp:150:89: error: incomplete type 'godot::GetTypeInfo<godot::Vector<godot::Ref<HandRankEvaluation> >, void>' used in nested name specifier
150 | GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
| ^~~~~~~~~~~~
scons: *** [godot/hand_ranking_evaluation.os] Error 1
scons: building terminated because of errors.
If you are using a type already registered with the Godot binding API you can use godot::Array
or godot::TypedArray<T>
(which enforces the type of any added item). For that matter godot::Array
already uses a godot::Vector<Variant>
under the hood.
You could implement a custom array container as a godot::RefCounted
but that likely wouldn't act as you would expect, and Godot's own types should be powerful enough for most use cases.