GDExtension calling some of my methods in register_virtuals?

Godot Version

4.1.4
( I have a backwards compatibility requirement )

Background

I’m working on a GDExtension that wraps existing MultiplayerPeers. Since constructors with params are not allowed, I have a static function that receives a MultiplayerPeer as reference, I create my instance, and store the reference in it. It looks something like this:

class CustomPeer: public MultiplayerPeerExtension {
    GDCLASS(CustomPeer, MultiplayerPeerExtension)

  private:
    Ref<MultiplayerPeer> _peer;

  protected:
    static void _bind_methods();

  public:
    static Ref<CustomPeer> wrap(Ref<MultiplayerPeer> p_peer);
    // ...
}

The rest of the methods are the ones declared in MultiplayerPeerExtension, and they just call through to the wrapped _peer - e.g. in _get_connection_status() I just do return _peer->get_connection_status();

Issue

After compiling the above and loading my Godot project, the editor consistently crashes. I’ve managed to get the following stack trace:

Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /lib/x86_64-linux-gnu/libc.so.6(+0x42520) [0x76e28ea42520] (??:0)
[2] godot::MultiplayerPeer::get_transfer_mode() const (??:0)
[3] CustomPeer::_get_transfer_mode() const (??:0)
[4] void godot::call_with_ptr_args_retc_helper<CustomPeer, godot::MultiplayerPeer::TransferMode>(CustomPeer*, godot::MultiplayerPeer::TransferMode (CustomPeer::*)() const, void const* const*, void*, IndexSequence<>) (??:0)
[5] void godot::call_with_ptr_args<CustomPeer, godot::MultiplayerPeer::TransferMode>(CustomPeer*, godot::MultiplayerPeer::TransferMode (CustomPeer::*)() const, void const* const*, void*) (??:0)
[6] godot::MultiplayerPeerExtension::register_virtuals<CustomPeer, godot::MultiplayerPeerExtension>()::{lambda(void*, void const* const*, void*)#10}::operator()(void*, void const* const*, void*) const (??:0)
[7] godot::MultiplayerPeerExtension::register_virtuals<CustomPeer, godot::MultiplayerPeerExtension>()::{lambda(void*, void const* const*, void*)#10}::_FUN(void*, void const* const*, void*) (??:0)
[8] godot() [0x2057e81] (??:0)
[9] godot() [0x204d15b] (??:0)
[10] godot() [0x3bb5cb2] (??:0)
[11] godot() [0x3bb6340] (??:0)
[12] godot() [0x3bb6ded] (??:0)
[13] godot() [0x11178a3] (??:0)
[14] godot() [0x11528e9] (??:0)
[15] godot() [0x403097d] (??:0)
[16] godot() [0x3b9d33c] (??:0)
[17] godot() [0x2092c13] (??:0)
[18] godot() [0x4f7f5e] (??:0)
[19] godot() [0x41e8b8] (??:0)
[20] /lib/x86_64-linux-gnu/libc.so.6(+0x29d90) [0x76e28ea29d90] (??:0)
[21] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x76e28ea29e40] (??:0)
[22] godot() [0x42a59a] (??:0)
-- END OF BACKTRACE --
================================================================
Aborted (core dumped)

This suggests to me that Godot instantiated my class and tried to call some methods on, on its own. In lieu of a debugger setup ( will get there eventually :smile: ), I decided to log all the method calls. Only these methods were called:

  1. The constructor
  2. _is_refusing_new_connections()
  3. _get_transfer_mode()
  4. _get_transfer_channel()

Without checking for the _peer reference’s validity, these calls fail, crashing the editor. I’ve added the checks, but I’m confused because I don’t instantiate the class anywhere, and yet it seems to be called.

Question

Does Godot just call methods on my GDExtension classes on its own? If so, why, when, and which methods?

Those callbacks are part of the properties of a MultiplayerPeer godot/scene/main/multiplayer_peer.cpp at 6b5b84c0c50135e88691e035d3e00c68a2ae5aa4 · godotengine/godot · GitHub So I guess they are being called to initialize those properties.

How are you compiling the extension?

I’m not sure but I might be having a related problem.

Thanks @mrcdk! Though that still makes me wonder why are property getters being called, but I guess I’ll dig around sometime to find out.

@enetheru I’m using this template repo, and setup my env with these commands:

git submodule update --init
cd godot-cpp && scons platform=linux custom_api_file=gdextension/extension_api.json
cd .. && scons platform=linux compiledb=true

From there I just run scons platform=linux from the repo root whenever something changes.

1 Like

ok thanks, is unrelated.

1 Like