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

Issues when passing CallableCustoms to C# #82978

Closed
Trey2k opened this issue Oct 7, 2023 · 3 comments
Closed

Issues when passing CallableCustoms to C# #82978

Trey2k opened this issue Oct 7, 2023 · 3 comments

Comments

@Trey2k
Copy link

Trey2k commented Oct 7, 2023

Godot version

399c9dc

System information

Arch linux - 6.5.5-arch1-1, Godot 4.1.2 Mono custom build

Issue description

I discovered this issue while trying to find the cause of WeaselGames/godot_luaAPI#170.

To help narrow it down I have created a minimal reproduction project as a Godot module. Not too much is going on, the main concern is this method right here:

Callable ExampleRefCounted::get_exmaple_callable() {
  ExampleCallableCustom *callable = memnew(ExampleCallableCustom(this));
  return Callable(callable);
}

It should be creating an instance of the ExampleCallableCustom which it does without issue for GDScript, but the deconstructor for it is called before C# can get its hands on it.

I added prints to the call method on the callableCustom, and constructors and contributors on both the callableCustom and refCounted.

C# Class
using Godot;
using System;

public partial class c_sharp : Node2D
{
	// Called when the node enters the scene tree for the first time.
	public override void _Ready()
	{
		ExampleRefCounted example_ref_coutned = new ExampleRefCounted();
		Callable example_callable = example_ref_coutned.GetExmapleCallable();
		example_callable.Call();
	}
}
GDScript Class
extends Node2D

func _ready() -> void:
	var example_ref_counted = ExampleRefCounted.new()
	var example_callable = example_ref_counted.get_exmaple_callable()
	example_callable.call()

This is the output we get:

Running GDScript Example
------------------------
ExampleRefCounted::ExampleRefCounted()
ExampleCallableCustom::ExampleCallableCustom()
ExampleCallableCustom::call()  0x92747E25
ExampleCallableCustom::~ExampleCallableCustom()
ExampleRefCounted::~ExampleRefCounted()
------------------------
Running C# Example
------------------------
ExampleRefCounted::ExampleRefCounted()
ExampleCallableCustom::ExampleCallableCustom()
ExampleCallableCustom::~ExampleCallableCustom()
------------------------

When C# does call the Callable.Call method we get this error which makes since seeing as the de constructor was called prior.

E 0:00:00:0400   Marshaling.cs:261 @ Godot.NativeInterop.godot_callable Godot.NativeInterop.Marshaling.ConvertCallableToNative(Godot.Callable& ): System.NullReferenceException: Object reference not set to an instance of an object.
  <C# Error>     System.NullReferenceException
  <C# Source>    /home/trey2k/Development/WeaselGames/Godot_Testing/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs:261 @ Godot.NativeInterop.godot_callable Godot.NativeInterop.Marshaling.ConvertCallableToNative(Godot.Callable& )
  <Stack Trace>  Marshaling.cs:261 @ Godot.NativeInterop.godot_callable Godot.NativeInterop.Marshaling.ConvertCallableToNative(Godot.Callable& )
                 Callable.cs:90 @ Godot.Variant Godot.Callable.Call(Godot.Variant[] )
                 c_sharp.cs:11 @ void c_sharp._Ready()
                 Node.cs:2093 @ Boolean Godot.Node.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name& , Godot.NativeInterop.NativeVariantPtrArgs , Godot.NativeInterop.godot_variant& )
                 CanvasItem.cs:1374 @ Boolean Godot.CanvasItem.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name& , Godot.NativeInterop.NativeVariantPtrArgs , Godot.NativeInterop.godot_variant& )
                 Node2D.cs:516 @ Boolean Godot.Node2D.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name& , Godot.NativeInterop.NativeVariantPtrArgs , Godot.NativeInterop.godot_variant& )
                 c_sharp_ScriptMethods.generated.cs:24 @ Boolean c_sharp.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name& , Godot.NativeInterop.NativeVariantPtrArgs , Godot.NativeInterop.godot_variant& )
                 CSharpInstanceBridge.cs:24 @ Godot.NativeInterop.godot_bool Godot.Bridge.CSharpInstanceBridge.Call(IntPtr , Godot.NativeInterop.godot_string_name* , Godot.NativeInterop.godot_variant** , Int32 , Godot.NativeInterop.godot_variant_call_error* , Godot.NativeInterop.godot_variant* )

I am not much of a C# developer so I may be missing something. I'm also unsure but think it may be related to #76108

Steps to reproduce

Build godot 4.1 branch with https://github.com/Trey2k/cscallable and run the TestProject from within

Minimal reproduction project

https://github.com/Trey2k/cscallable

@raulsntos
Copy link
Member

As explained in the C# differences documentation page, custom Callables are not supported in C#.

This means the only Callables that can be used in C# are the ones created using a method name and an Object instance, or Callables created from C#. It looks like you are using GDExtensions to create a custom Callable type, so that would fall into the unsupported scenario.

@raulsntos raulsntos closed this as not planned Won't fix, can't repro, duplicate, stale Oct 7, 2023
@Trey2k
Copy link
Author

Trey2k commented Oct 7, 2023

It looks like you are using GDExtensions to create a custom Callable type, so that would fall into the unsupported scenario.

All good if it's unsupported. I am not using gdExtension here though, this is as a core engine module. Not sure if it makes a difference either way though in this case.

@raulsntos
Copy link
Member

Ah, custom Callables aren't supported even if they are implemented in the engine. For example CallableCustomBind and CallableCustomUnbind (the Callables you get when you use the bind and unbind methods) are also unsupported in C#.

Just to be clear, this is not intentional, it just hasn't been implemented yet.

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

2 participants