Skip to content
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

Callable::bind no longer unwraps arrays. Cannot convert argument 1 from [missing argptr, type unknown] #64668

Closed
TokisanGames opened this issue Aug 20, 2022 · 3 comments

Comments

@TokisanGames
Copy link
Contributor

TokisanGames commented Aug 20, 2022

Godot version

Godot 4 Alpha 14

System information

Windows 11/64, RTX 3070, Vulkan

Issue description

The key issue is that the change from Object.connect(signal..., binds[]) and Callable(obj, signal).bind() have changed behavior with bind, which no longer unwraps arrays.

Another aspect is that we apparently have no ability to receive, create or pass along varargs. So all C++ functions that receive varargs can only be called directly, and not in derivative functions.

If either there was a way to convert an array into a vararg, or the behavior stayed the same, it wouldn't be an issue. But because both happened it became an issue.

I wrote my own connect wrapper function to protect my game signal connects from the quirks in the engine. Try to connect more than once, and get console spam. Disconnect when not connected and get spammed. Disconnect and reconnecting scenes from the tree, and state machines with states reusing timers and other reasons means signals are connecting and disconnecting all the time. I don't want console spam to slow the engine, and I don't to write a few lines of validation code on every signal connection. Hence a signal wrapper.

However now Alpha14 broke it, it seems in #63595. Before, the binds array was unwrapped. Now bind takes a vararg. Any passed array no longer gets unwrapped and the whole array is accepted as one argument.

This might work ok if we could receive, process, and create varargs. AFAIK we can't. So effectively any C++ vararg function treats GDscript as a second class citizen as we can't derive from those classes, can't override them, and can't wrap them.

Steps to reproduce

Here is my reconnect function, a signal connection, and the called function. This has worked fine until now, including the GD3 equivalent w/o Callable.

extends Node3D

static func reconnect(obj: Object, signal_name: String, call_obj: Object, call_back: String, binds: Array = [], flags: int = 0) -> void:
	if obj and call_obj:
		var cb := Callable(call_obj, call_back)
		if obj.has_signal(signal_name) and cb.is_valid() and not obj.is_connected(signal_name, cb):
			obj.connect(signal_name, cb.bind(binds), flags)

func _ready():
	var timer := Timer.new()
	add_child(timer)
	reconnect(timer, "timeout", self, "play_song", [0])
	timer.start(1)

func play_song(track:int) -> void:
	pass

When the callback occurs I get this error:

ERROR: Error calling from signal 'timeout' to callable: 'Node3D::play_song': Cannot convert argument 1 from [missing argptr, type unknown] to int..
   at: emit_signalp (core/object/object.cpp:1002)

I've found I can change my called function declaration. Kinda hacky and I lose static typing.

func play_song(track:Array) -> void:
    print(Array)    # [0]

I've also found I can create a Callable in the client call. Exactly the kind of thing I wanted to avoid. It's only two extra words and formatting, but I have to do it across my whole codebase only because it appears that I can't convert binds[] into a vararg or use vararg as a function declaration.

# Old
Util.reconnect(button, "pressed", self, "play_song", [music_list.size()-1])
# New
Util.reconnect(button, "pressed", Callable(self, "play_song").bind(music_list.size()-1))

Also the docs are out of date. They still say I can pass binds to connect, though I cannot.

@Calinou Calinou added this to the 4.0 milestone Aug 20, 2022
@Calinou Calinou moved this to To Assess in 4.x Priority Issues Aug 20, 2022
@TokisanGames TokisanGames changed the title Callable::bind Cannot convert argument 1 from [missing argptr, type unknown] Callable::bind no longer unwraps arrays. Cannot convert argument 1 from [missing argptr, type unknown] Aug 20, 2022
@YuriSizov
Copy link
Contributor

Since this is not a bug, but a missing feature, it should be tracked in the proposals repo with a proper proposal. There is one made recently, in fact: godotengine/godot-proposals#6034. So closing this in favor of that.

@YuriSizov YuriSizov closed this as not planned Won't fix, can't repro, duplicate, stale Jan 6, 2023
@github-project-automation github-project-automation bot moved this from To Assess to Done in 4.x Priority Issues Jan 6, 2023
@YuriSizov YuriSizov removed this from the 4.0 milestone Jan 6, 2023
@TokisanGames
Copy link
Contributor Author

@YuriSizov Why not leave it open until #71000 closes it?

@YuriSizov
Copy link
Contributor

Because this is a feature proposal and feature proposals are tracked in the proposals repo. And there is a feature proposal for it, which that PR will also close.

reduz added a commit to reduz/godot that referenced this issue Jan 6, 2023
Restores 3.x functionality that was removed in the Signal/Callable refactor of 4.0.

Fixes godotengine#64668.
Implements godotengine/godot-proposals#6034

Usage:

```GDScript

callable.bindv([arg1,arg2,arg3])

```
Streq pushed a commit to Streq/godot that referenced this issue Feb 9, 2023
Restores 3.x functionality that was removed in the Signal/Callable refactor of 4.0.

Fixes godotengine#64668.
Implements godotengine/godot-proposals#6034

Usage:

```GDScript

callable.bindv([arg1,arg2,arg3])

```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants