-
-
Notifications
You must be signed in to change notification settings - Fork 603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GDExtension objects made without memnew miss callbacks and crash #1057
Comments
I investigated a bit more.
None of the other ways of instantiating Wrapped::Wrapped(const StringName p_godot_class) {
_owner = godot::internal::gde_interface->classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
} So you end up with both This situation could be avoided by setting both |
Moved to godot-cpp repository as it appears to be specific to the C++ |
I tested composition ( class Test : public Node3D {
GDCLASS(Test, Node3D);
protected:
static void _bind_methods();
public:
Area3D area;
void on_mouse_entered_area();
void _ready() override;
};
void Test::_bind_methods() {
ClassDB::bind_method(D_METHOD("on_mouse_entered_area"),
&Test::on_mouse_entered_area);
}
void Test::on_mouse_entered_area() {
UtilityFunctions::print("hello");
}
void Test::_ready() {
area.connect("mouse_entered", Callable(this, "on_mouse_entered_area"));
area.add_child( /* some collision shape */ );
add_child(&area);
}
I still can't tell whether this usage is meant to be supported or not. |
FWIW, in case it's useful:
|
@paulmiller GDExtension objects must indeed be instantiated using This should be properly documented. |
There is a docs issue for mentioning that |
Godot version
4.0
System information
Arch Linux
Issue description
Say I have a GDExtension class
Foo
:If I instantiate
Foo
in C++ usingnew
, the resulting object seems to work at first; I can add it to the scene tree, and add a Sprite2D under it which appears normally:But it misbehaves in surprising ways:
Foo::_enter_tree()
doesn't get called foradd_child(f)
, and if I try to callf.hello()
, the game crashes.Foo
objects instantiated withmemnew
don't have this problem.If I'm reading the code correctly, every extension object (
Foo
in this example) gets assigned a corresponding Godot engine object (Node
in this example). Each contains an opaque pointer to the other:Foo
inherits fromWrapped
. TheWrapped
constructor setsWrapped::_owner
to point to theNode
.Node
inherits fromObject
.ClassDB::set_object_extension_instance
setsObject::_extension_instance
to point to theFoo
.It seems like it shouldn't matter how I instantiate
Foo
-new Foo
,memnew(Foo)
, andstd::make_unique<Foo>()
should all call theWrapped
constructor.Although, the existence of the
_extension_instance
pointer implies some limitations on how I can useFoo
. For example, astd::vector<Foo>
presumably wouldn't work, since vector reallocation wouldinvalidate the
_extension_instance
of each correspondingNode
.It's not clear to me exactly how I'm allowed to use GDExtension objects, and so I can't tell whether this is a Godot bug or a documentation bug. Maybe
new Foo
isn't supposed to work in the first place?Specifically, which of the following is allowed?
Foo
withnew
(as above)Foo
withdelete
(throws exception if theFoo
was created withmemnew
!)Foo
objects in a reallocating container likestd::vector<Foo>
Foo
with a managed pointer likestd::unique_ptr<Foo>
Foo
as a field of another GDExtension class, like:Foo
as a field of a regular class, like:If any of these uses are forbidden, they should be called out in the documentation.
Steps to reproduce
The attached project has the above code, and some other test functions.
make-node-test.zip
make-node-test/extension/godot-cpp/
cd make-node-test/extension/out/
cmake ..
and build, e.g.CC=gcc CXX=g++ cmake -G Ninja .. && ninja
cp libfoo.so ../../project/
<Godot executable> --path ../../project/
Minimal reproduction project
make-node-test.zip
The text was updated successfully, but these errors were encountered: