Open tbillington opened 8 months ago
Working with GDExtensions and C# certainly has been a bit cumbersome! Great proposal!
However, with a csharp focused godot project these extensions are inaccessible.
Some of our C# users have helped us document how to use Terrain3D in C# and are using it without issue. See the "Detecting" and "Calling" sections. So GDextensions in C# may be inconvenient, but are not inaccessible.
Is this information available in ClassDB
? As such, access via reflection (as mentioned in the Terrain3D
example) would always be a workaround:
var terrain = ClassDB.Instantiate("Terrain3D");
terrain.AsGodotObject().Set("storage", ClassDB.Instantiate("Terrain3DStorage"));
terrain.AsGodotObject().Set("texture_list", ClassDB.Instantiate("Terrain3DTextureList"));
terrain.AsGodotObject().Call("set_collision_enabled", true);
However, it would probably still be nice if Godot provided an option to include more classes in the C# code generation, as it already has the entire codegen infrastructure in place. This would allow type-safe and idiomatic APIs rather than dynamic ones.
Incidentally related: ongoing discussion of porting C# itself to GDExtension: #7895.
GDExtension classes are registered in ClassDB and we can just retrieve the information needed from there. No need for the GDExtension source code.
As mentioned by @Bromeon, any GDExtension class can be consumed using the reflection-like APIs available in GodotObject
(same as interop with GDScript classes). This means consuming GDExtensions is currently possible, but not ideal (because we lose type safety).
We do want to improve support for GDExtensions in C#, which includes creating them as well as consuming them.
If we were to use the codegen that exists in the editor (the bindings generator that generates the glue for GodotSharp), then there are a few things to keep in mind:
Also, the proposed workflow assumes GDExtensions are added from the Asset Library using the editor to trigger the C# bindings generation. How would this work if an user places a GDExtension in their projects from outside the editor? For example, if I have a project in GitHub that I download which includes GDExtensions already.
I think the bindings generation should be part of the MSBuild compilation, either using Source Generators or MSBuild tasks. I mentioned this before in https://github.com/godot-rust/gdext/issues/166#issuecomment-1574199958.
Would it make sense to have GDExtensions produce their own JSON API document similar to godot --dump-extension-api extension_api.json
?
That way extensions could reference each other, rather than relying on the too-late ClassDB registration? Then its something build time for source generators to hook into and would be for more than just dotnet usage: extensions could reference each other.
Would it make sense to have GDExtensions produce their own JSON API document similar to
godot --dump-extension-api extension_api.json
?That way extensions could reference each other, rather than relying on the too-late ClassDB registration? Then its something build time for source generators to hook into and would be for more than just dotnet usage: extensions could reference each other.
This needs some testing, but this may already work to some degree.
If you run godot --dump-extension-api
in a project that has some GDExtensions in it, it will actually put information for the classes from the GDExtensions into the extension_api.json
. In theory, you should be able to then recompile your GDExtensions with this new JSON and it'll generate classes for them. I haven't actually ever tried this 2nd part, though :-)
But even if it does work, this isn't an ideal workflow, since it requires building all your GDExtensions, generating the extension_api.json
and then re-building again (so, building twice).
But even if it does work, this isn't an ideal workflow, since it requires building all your GDExtensions, generating the extension_api.json and then re-building again (so, building twice).
But in this instance of the C# bindings, the build is MSBuild right so assuming the Extensions are already built and registered we could use that as the source instead of ClassDB directly?
Edit: that's work thats already happening somewhere right? I've never been able to find where
@raulsntos
The following step could only be done by the nuget provider using a GDExtension C# binding addon
Ideally
godot --dump-extension-api --gdextension
will create each extension_api-gdextension-Name.json
for each of the GDExtensions. Obviously, it is expected only one e.g. c++ GDExtension is present
The bindings generator retrieves everything from ClassDB and generates the glue, we would probably need to refactor it so we can allow generating only certain classes (like the ones registered through GDExtensions).
The user only consumes the nuget, no c# binding codes that require unsafe code compilation will be involved
We may be using internal APIs in the generated bindings source code. This would mean code generated in a user project would not compile.
The generated bindings source code uses unsafe code blocks which would require user projects to also enable unsafe code blocks and, in my opinion, this is not acceptable.
Maybe we could modify these steps to work and do a script to automate them ? They don't work with me at least
Update to this topic? When will this feature planned?
@DmitriySalnikov
Do you have a recommendation?
Do you have a recommendation?
Don't use ClassDB.Call
/Set
/Get
in the core of the engine for C# bindings as I have.
Anyway, the bindings generator is already in the engine. It requires modifications, but this is most likely not a high priority. I'm definitely not going to do that.
@mihe => it seems ClassDB.Call/Set/Get
is not recemmended
GodotObject.Get, GodotObject.Set and GodotObject.Call
https://github.com/godot-jolt/godot-jolt/issues/632#issuecomment-1750546745
it seems
ClassDB.Call/Set/Get
is not recemmended
As mentioned in the comment you linked, they're meant to be a workaround. They're pretty much the only alternative available from GDExtension right now, and as pointed out earlier in this thread the situation is similar to interop with GDScript, where you would also rely on GodotObject
(or ClassDB
I guess), as seen in the documentation.
@DmitriySalnikov => elaborate?
Anyway, the bindings generator is already in the engine. It requires modifications
@raulsntos => care to share your latest view?
This issue has an impact on Unity Users using c# moving to Godot.
=> elaborate?
Describe the project you are working on
3D multiplayer game targeting Steam using C#.
Mid-port from Unity.
Uses Steam Matchmaking/Networking to allow easy joining/inviting between friends, and Steam Datagram Relay (SDR) to achieve connections between players without port forwarding etc.
Describe the problem or limitation you are having in your project
Many important features and 3rd party integrations are implemented as GDExtensions in Godot. In our project: GodotSteam and SteamMultiplayerPeer.
However, with a csharp focused godot project these extensions are inaccessible.
We've written a GDScript "bridge" for for GodotSharp that exposes and proxies calls from CSharp, but it's time consuming and error prone.
Not having access to community extensions is a big limitation of Godot currently (for csharp developers/ex-unity).
Describe the feature / enhancement and how it helps to overcome the problem or limitation
With the continued focus on supporting csharp as a "first class" option in Godot, it follows that being able to access GDExtensions would be of increased importance.
Generating csharp bindings on extension "import" when csharp use is detected would bring csharp feature parity closer.
Ideally this would not be something extension developers have to individually and manually add to their extensions. It should be effortless/automatic, not requiring opt in. Otherwise I fear it just won't happen (the current situation).
Optional Extra
Support the work to allow generating bindings not just for csharp, but for other language extensions like rust and swift.
Achieving arbitrary language binding generation would greatly increase the capability of Godot as a multi-langauge extension and fully unlock it for developers from other languages.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
GDExtensions would include their source when being packaged. (I assume source is required to generate csharp bindings)
In the editor, upon download from the Godot Asset Library, Godot will generate csharp bindings and place them in the project, potentially alongside the extension in
addons
.Any required changes to .csproj or .sln would be made after generating the bindings.
If this enhancement will not be used often, can it be worked around with a few lines of script?
If users are not using Godot_mono, or in future don't have the csharp GDExtension enabled, generating bindings can be skipped.
Is there a reason why this should be core and not an add-on in the asset library?
I make this proposal here because csharp code is in core/the godot main repository.