Description
Godot version
4.3
godot-cpp version
4.3 (e298f43)
System information
macOS Sonoma 14.6.1
Issue description
With the removal of UtilityFunctions::is_instance_valid()
(#1513), it is impossible to validate an Object passed to a GDExtension method as a Variant.
Spawned from this comment. Using ObjectDB::get_instance()
as suggested here and here isn't a perfect replacement. Starting with a Variant that represents a freed Object, we're unable to get an object ID in order to use ObjectDB::get_instance(). After ensuring a Variant is of type Object, an operator Object*() call causes a crash.
Previously, UtilityFunctions::is_instance_valid()
could be used to validate an object. It's possible to use variant.stringify() == "<Freed Object>"
as a hacky workaround although obviously not ideal.
Steps to reproduce
Add the following method to a GDExtension class.
// Must validate supplied object
godot_error MyLib::dummy(const Variant v) {
// Side effects for other Variant types would necessitate accepting a Variant rather than Object*
if (v.get_type() != Variant::OBJECT) return ERR_CANT_CREATE;
// if (v.stringify() == "<Freed Object>") return ERR_CANT_CREATE; // Hacky solution
auto o = v.operator Object*(); // Crashes here if object was previously freed
if (o == NULL) return ERR_CANT_CREATE;
auto id = o->get_instance_id();
auto x = ObjectDB::get_instance(id);
if (x == NULL) return ERR_CANT_CREATE;
return OK;
}
Use the GDExtension function via GDScript as follows.
var o = Object.new()
var lib = MyLib.new()
assert(lib.dummy(o) == OK) # Expect object to be valid
o.free()
assert(lib.dummy(o) != OK) # Expect object to be invalid
Minimal reproduction project
N/A