From 1a781f8c98acf27275a3c6054db2cb9bcad2962b Mon Sep 17 00:00:00 2001 From: Jeff Ward Date: Wed, 30 Oct 2024 21:48:06 -0400 Subject: [PATCH] fix: Fix index getters / setters that return variants Index getters / setters that return variants were crashing because of a bad attempt to cast the object held in the Variant to an Object. This may be a bigger issue but it is fixed for arrays. refs: #26 --- src/cpp/dart_bindings.cpp | 9 ++++----- .../godot_dart/lib/src/variant/variant.dart | 7 ++++++- .../src/generators/builtin_type_generator.dart | 18 +++++++++++++++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/cpp/dart_bindings.cpp b/src/cpp/dart_bindings.cpp index cc157c5..eef80fa 100644 --- a/src/cpp/dart_bindings.cpp +++ b/src/cpp/dart_bindings.cpp @@ -791,9 +791,9 @@ void gd_object_to_dart_object(Dart_NativeArguments args) { } GDEWrapper *gde = GDEWrapper::instance(); - // Defaults for non-engine classes + + // Default for non-engine classes void *token = gde->get_library_ptr(); - const GDExtensionInstanceBindingCallbacks *bindings_callbacks = &DartGodotInstanceBinding::engine_binding_callbacks; Dart_Handle bindings_token = Dart_GetNativeArgument(args, 2); if (!Dart_IsNull(bindings_token)) { @@ -805,12 +805,11 @@ void gd_object_to_dart_object(Dart_NativeArguments args) { } uint64_t token_int = 0; Dart_IntegerToUint64(address, &token_int); - token = (void *)token_int; - bindings_callbacks = &DartGodotInstanceBinding::engine_binding_callbacks; + token = (void *)token_int; } DartGodotInstanceBinding *binding = (DartGodotInstanceBinding *)gde_object_get_instance_binding( - reinterpret_cast(object_ptr), token, bindings_callbacks); + reinterpret_cast(object_ptr), token, &DartGodotInstanceBinding::engine_binding_callbacks); if (binding == nullptr) { Dart_SetReturnValue(args, Dart_Null()); } else { diff --git a/src/dart/godot_dart/lib/src/variant/variant.dart b/src/dart/godot_dart/lib/src/variant/variant.dart index 0ae0e4d..599f40a 100644 --- a/src/dart/godot_dart/lib/src/variant/variant.dart +++ b/src/dart/godot_dart/lib/src/variant/variant.dart @@ -172,6 +172,9 @@ class Variant implements Finalizable { Variant([Object? obj]) { if (obj == null) { gde.ffiBindings.gde_variant_new_nil(nativePtr.cast()); + } else if (obj is Variant) { + throw ArgumentError.value( + obj, 'obj', 'Do not construct Variants with Variants.'); } else { _initFromObject(obj); } @@ -355,9 +358,11 @@ Object? convertFromVariantPtr( Pointer ptr = arena.allocate(sizeOf()); c!(ptr.cast(), variantPtr); + final token = + typeInfo?.bindingToken ?? GodotObject.sTypeInfo.bindingToken; ret = gde.dartBindings.gdObjectToDartObject( ptr.value, - typeInfo?.bindingToken, + token, ); break; diff --git a/tools/binding_generator/lib/src/generators/builtin_type_generator.dart b/tools/binding_generator/lib/src/generators/builtin_type_generator.dart index b7e5860..1b956da 100644 --- a/tools/binding_generator/lib/src/generators/builtin_type_generator.dart +++ b/tools/binding_generator/lib/src/generators/builtin_type_generator.dart @@ -306,17 +306,29 @@ void _writeMethods(CodeSink o, BuiltinClass builtin) { // TODO: This can be made more efficient for PackedXArray, but for now we're going // to just use Variant's indexed getter / setters if (builtin.indexingReturnType != null && builtin.name != 'Dictionary') { + final returnTypeCategory = + GodotApiInfo.instance().getTypeCategory(builtin.indexingReturnType!); var dartReturnType = godotTypeToDartType(builtin.indexingReturnType); o.b('$dartReturnType operator [](int index) {', () { o.p('final self = Variant(this);'); o.p('final ret = gde.variantGetIndexed(self, index);'); - o.p('return convertFromVariant(ret, null) as $dartReturnType;'); + if (dartReturnType == 'Variant') { + o.p('return ret;'); + } else if (returnTypeCategory == TypeCategory.engineClass) { + o.p('return convertFromVariant(ret, $dartReturnType.sTypeInfo) as $dartReturnType;'); + } else { + o.p('return convertFromVariant(ret, null) as $dartReturnType;'); + } }, '}'); o.nl(); o.b('void operator []=(int index, $dartReturnType value) {', () { o.p('final self = Variant(this);'); - o.p('final variantValue = Variant(value);'); - o.p('gde.variantSetIndexed(self, index, variantValue);'); + if (dartReturnType == 'Variant') { + o.p('gde.variantSetIndexed(self, index, value);'); + } else { + o.p('final variantValue = Variant(value);'); + o.p('gde.variantSetIndexed(self, index, variantValue);'); + } }, '}'); o.nl(); }