godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.79k stars 21.13k forks source link

[Cross-language scripting] Passing a Callable lambda parameter (GDScript calls C#) causes a null reference exception #76108

Open viljami-j opened 1 year ago

viljami-j commented 1 year ago

Godot version

v4.0.1.stable.mono.official [cacf49999]

System information

Windows 11, x86_64

Issue description

What doesn't work: It appears that Callables defined in a certain way fail to survive marshaling.

Observe the results of these different options below:

Option 1: csharp_test_script_instance.SetCallable(Callable(self, "_some_function"))

Option 2: csharp_test_script_instance.SetCallable(func (): print("Lambda!"))

Option 3: csharp_test_script_instance.SetCallable(Callable(func (): print("Lambda passed into a Callable!")))

Here in GDScript we invoke a C# function that runs the given Callable: csharp_test_script_instance.RunCallable()

Option 1: works Option 2: null reference exception Option 3: null reference exception

Error: image

How I expect it to work: I should be able to call Callables defined in GDScript in C# as well.

Steps to reproduce

On the minimal reproduction project:

  1. Open 'main_test_script.gd'
  2. Observe what happens when you switch between the commented options & run the scene.

Minimal reproduction project

MinimalReproduction.zip

dalexeev commented 1 year ago
raulsntos commented 1 year ago

I don't think GDScript lambda Callables are supported in C#. See https://docs.godotengine.org/en/stable/tutorials/scripting/c_sharp/c_sharp_differences.html#callable.

When Callables are created from other languages, C# only supports the basic ones created with the constructor that takes the target Object and the method name. Custom Callables are unsupported.

I think this is unrelated to https://github.com/godotengine/godot/issues/75421. The C# marshaling just assumes every Callable always has a target Object and a method name.