godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

Expose non-template versions of vararg methods

Open kevinresol opened this issue 10 months ago • 6 comments

Godot version

4.3.stable

godot-cpp version

4.3

System information

MacOS 15.2

Issue description

For custom scripting support and other dynamic uses, it would be nice to expose vararg methods as non-templated.

Currently, the dynamic (non-template) version (<fn>_internal) for classes and utility_functions already exists, although marked private: . As for builtin_classes there are no equivalent, the closes thing would be the private _method_bindings struct but those are raw method pointers doesn't give us nice signature and return value handling.

If this suggestion is accepted, I can raise a PR to remove the private accessor for classes and utility_functions, and refactor builtin_classes bindings to expose the corresponding *_internal methods.

Steps to reproduce

N/A

Minimal reproduction project

N/A

kevinresol avatar Jan 30 '25 11:01 kevinresol

I don't think we should make the *_internal() methods public. One of the core design goals of godot-cpp is to be API compatible with Godot's internal APIs as used by Godot modules, and Godot modules don't have those methods.

Would using object->callv("name", array_of_arguments) work for you?

dsnopek avatar Mar 13 '25 19:03 dsnopek

Would using object->callv("name", array_of_arguments) work for you?

Technically, this approach will work, though it does introduce some overhead. I was under the impression that all the necessary dynamic code is already in place, and that we would only need a flag in Python to expose it for those who require it.

kevinresol avatar Mar 29 '25 07:03 kevinresol

I was under the impression that all the necessary dynamic code is already in place, and that we would only need a flag in Python to expose it for those who require it.

Like I said above, using the same API as Godot is a core design goal of godot-cpp. While there are existing inconsistencies, I don't think we should introduce any new ones, even optional ones.

dsnopek avatar Mar 31 '25 13:03 dsnopek

I’d like to respectfully challenge the decision to keep the _internal vararg methods private and not expose non-template versions.

This creates a real roadblock for anyone trying to implement a new scripting language for Godot using godot-cpp. The templated call methods aren't usable in dynamic language contexts where argument types and counts aren't known at compile time. callv can't help here either—it only works on Object, which means it's not applicable for things like UtilityFunctions, Callable, or Signal.

From what I understand, even the official GDScript and C# integrations seem to rely on internal support for dynamic calls. While I don’t know their internals in depth, this suggests there's precedent and infrastructure in place for dynamic invocation that’s simply not exposed in godot-cpp. It makes little sense for godot-cpp to withhold the same low-level access from external language implementors, who have no workaround unless they start duplicating efforts around the GDExtension C API.

By keeping these methods private, godot-cpp effectively blocks third-party language implementors from reaching feature parity or even basic interop in some cases. Exposing these vararg methods would make the API much more flexible and open up support for scripting languages beyond what's officially maintained.

I hope this can be reconsidered—it's a relatively small change that would have a big impact for community extensibility.

kevinresol avatar Apr 20 '25 00:04 kevinresol

It looks like there are non-templated versions of some of these methods in Godot, but under different names, for example:

  • Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error)
  • Object::emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount)
  • Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error)

I'm not sure if this applies to all the methods that you want access to, but it would definitely make sense to come up with a way to expose the ones that Godot has with the same name (which seems to be mostly with the p suffix). If there are any that don't have equivalents in Godot, then they should be added to Godot before we add them here.

It makes little sense for godot-cpp to withhold the same low-level access from external language implementors, who have no workaround unless they start duplicating efforts around the GDExtension C API.

One of the core design goals of godot-cpp is to be API compatible with Godot's internal APIs as used by Godot modules. We're slowly removing all the API differences that already exist - adding new differences is just adding a new bug that will need to be fixed later.

I think using the GDExtension C API and the helpers in godot::internal:: is a valid workaround. If you use stuff from godot::internal::, you are very explicitly opting into using things that aren't part of the public API surface, which doesn't need to be compatible with Godot. If there's an addition to godot::internal:: that would make what you want to do easier, I'd potentially be open to that

Also, using a patched version of godot-cpp is also a valid workaround. It's compiled into your extension, and so your customizations won't affect users of your extension. The project is Open Source, and one of the advantages of that is that you can make your changes anyway, even if the maintainers disagree with those changes :-)

dsnopek avatar Apr 29 '25 23:04 dsnopek

Supporting *p methods in line with Godot's own API would essentially be sufficient, I think.

In most cases, it would just involve exposing the existing *_internal methods as *p, along with some minor refactoring for built-in classes like Callable and Signal.

kevinresol avatar May 01 '25 04:05 kevinresol