raulsntos / godot-dotnet

MIT License
86 stars 13 forks source link

Callable Bind only supports no-parameter Call #5

Closed scgm0 closed 7 months ago

scgm0 commented 7 months ago

Godot version

v4.3.dev.mono.custom_build [de932f29d]

Godot .NET packages version

https://github.com/raulsntos/godot-dotnet/commit/f6c04004fb9a82b56cfa71ab51133f2f37b29bbf

System information

Godot v4.3.dev.mono (de932f29d) - Arch Linux #1 ZEN SMP PREEMPT_DYNAMIC Sat, 06 Apr 2024 23:01:55 +0000 - Wayland - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1650 (nvidia; 550.67) - Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 Threads)

.NET information

8.0.203

Issue description

Callable Bind will crash directly when using Call with parameters. Code that runs fine:

Callable.From<int, int>((a, b) => GD.Print(a + b))
    .Bind([5, 6])
    .Call();

Running code that crashes:

Callable.From<int, int>((a, b) => GD.Print(a + b))
    .Bind([5, 6])
    .Call([0, 0]);

Steps to reproduce

Callable.From<int, int>((a, b) => GD.Print(a + b))
    .Bind([5, 6])
    .Call([0, 0]);

Minimal reproduction project

N/A

raulsntos commented 7 months ago

You didn't specify what version of the Godot .NET packages you are using, it seems you just copied the Godot version. So I don't know if this is a nightly build or a custom build. There are no nightly builds with the fix, you'll have to make a custom build for now (use commit f6c04004fb9a82b56cfa71ab51133f2f37b29bbf or newer).

scgm0 commented 7 months ago

You didn't specify what version of the Godot .NET packages you are using, it seems you just copied the Godot version. So I don't know if this is a nightly build or a custom build. There are no nightly builds with the fix, you'll have to make a custom build for now (use commit f6c0400 or newer).

Sorry, the Godot .NET version information has been updated, I misunderstood what it should say ( By the way, there is an error message (only displayed in the terminal console, not in the godot editor):

Unhandled Exception: System.ArgumentException: Invalid argument count for invoking callable. Expected 2 arguments, received 4. (Parameter 'args')
   at Godot.Callable.<ThrowIfArgCountMismatch>g__ThrowArgCountMismatch|20_0(Int32, Int32, String) + 0x181
   at Godot.Callable.<From>g__Trampoline|23_0[T0,T1](Object, NativeGodotVariantPtrSpan, NativeGodotVariant&) + 0x81
   at Godot.NativeInterop.DelegateCallable.Call(NativeGodotVariantPtrSpan, NativeGodotVariant*, GDExtensionCallError*) + 0x3d
   at Godot.Bridge.CustomCallable.Call_Native(Void*, NativeGodotVariant**, Int64, NativeGodotVariant*, GDExtensionCallError*) + 0x80

So is this expected behavior?

raulsntos commented 7 months ago

Yes, it's expected behavior. You have a Callable with 2 parameters, when you use Bind you are essentially assigning values to those parameters already so when you use Call you have to pass only the remaining parameters.

Callable callable = Callable.From<int, int, int>((a, b, c) => GD.Print(a + b + c));

callable.Call([1, 2, 3]); // Must pass 3 parameters.

callable.Bind([3]).Call([1, 2]); // Must pass 2 parameters, because we already bound 1.

callable.Bind([2, 3]).Call([1]); // Must pass 1 parameter, because we already bound 2.

callable.Bind([1, 2, 3]).Call(); // Must not pass any parameters, because we already bound them all.
scgm0 commented 7 months ago

Yes, it's expected behavior. You have a Callable with 2 parameters, when you use Bind you are essentially assigning values to those parameters already so when you use Call you have to pass only the remaining parameters.

Callable callable = Callable.From<int, int, int>((a, b, c) => GD.Print(a + b + c));

callable.Call([1, 2, 3]); // Must pass 3 parameters.

callable.Bind([3]).Call([1, 2]); // Must pass 2 parameters, because we already bound 1.

callable.Bind([2, 3]).Call([1]); // Must pass 1 parameter, because we already bound 2.

callable.Bind([1, 2, 3]).Call(); // Must not pass any parameters, because we already bound them all.

ok