创建一个与“godot::Variant”兼容的新数组类型?

Creating a new array type compatible with `godot::Variant`?

提问人:shackra 提问时间:11/5/2023 更新时间:11/5/2023 访问量:78

问:

使用 GDExtension 编写一个附加组件, 我希望在 Godot 4 上返回一组自定义类型.我的第一个想法是编写一个类似 的类型,但我发现编译器会抱怨,因为这个新类型与 不兼容。godot::Vector<godot::Ref<MyStruct>>godot::Variant

所以,我想知道我应该如何满足 .编译器错误如下:godot-cpp

➜  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.
C++ 矢量 Godot

评论

1赞 Kozydot 11/5/2023
godot::Vector<godot::Ref<MyStruct>>不是 GDExtension API 中支持的类型。这是因为 GDExtension API 是自定义类型,而 GDExtension API 不知道如何处理这些向量。Ref<MyStruct>
0赞 SilicDev 11/6/2023
@Kozydot不完全正确。GDExtension API 不处理任何类型的 s,它只是一个智能指针,可以看作是 API 的指针。godot::Vectorgodot::Ref<T>godot::RefCounted

答:

1赞 SilicDev 11/5/2023 #1

如果您使用的是已在 Godot 绑定 API 中注册的类型,则可以使用 or (强制执行任何添加项的类型).就此而言,已经使用了引擎盖下。godot::Arraygodot::TypedArray<T>godot::Arraygodot::Vector<Variant>

你可以实现一个自定义数组容器,但这可能不会像你预期的那样运行, Godot 自己的类型应该足够强大,适合大多数用例.godot::RefCounted

评论

0赞 shackra 11/6/2023
我看到访问数组上的项目返回,我怎样才能将其转换为我的?godot::TypedArray<T>godot::VariantMyStruct
1赞 SilicDev 11/6/2023
我相信如果需要,应该给你一个有效的指针,因为可以是一个指针。godot::Object::cast_to<T>(godot::Object *)godot::Variant
0赞 shackra 11/6/2023
但我是从 tho 继承的godot::RefCounted
0赞 SilicDev 11/6/2023
godot::RefCounted继承自 因此,只要基础类型继承自 RefCounted,就可以将对象指针强制转换为 RefCounted。对于 RefConted 类型,您还可以直接将结果分配给 a,因为 Ref 会覆盖 ,以便从指针创建 Ref。如果要确保将 a 转换为 是安全的,可以检查 的返回。godot::Objectgodot::Ref<T>=operatorgodot::Variantgodot::Object *godot::Variant::get_type()
1赞 SilicDev 11/6/2023
这应该与从 继承它的方法相同。RefCountedObject
-1赞 Dimitri Troncquo 12/8/2023 #2

其他问题。

我注意到 godot 定义了一个宏,它用它来为其变体创建 TypedArrray 实现。MAKE_TYPED_ARRAY

将其用于我们自己的类型是否必要或有益?例如:MAKE_TYPED_ARRAY(MyClass, Variant::OBJECT)

编辑:移至如何在gdextension中正确配置TypedArrays

评论

2赞 shackra 12/13/2023
我认为,这值得质疑
0赞 Dimitri Troncquo 12/13/2023
好电话。我在上面添加了一个链接。