Using any C++ library in Godot (blog.conan.io)

152 points by czoido 13 hours ago

voodooEntity 12 hours ago

Was playing arround recently building an RTS with godot until i just hit the ceilling of what i could handle with gdscript performance wise.

Than started to move alot of heavy logic to c++ simulation : tedious indeed but the results speak for themself.

Basically allows me to use godot for things like menus dialogues and similar stuff while running the true heavy work in a c++ simulation.

8-prime 10 hours ago

What motivated you to use c++ rather than C#? Especially when you mention the usage of c++ being tedious, when I would argue using C# is equally straight forward as gdscript is.

voodooEntity 8 hours ago

A combination of two factors that are rather specific to myself. One being that even tho its quite some time ago i have a bit of c++ experience, while i never tried to code C#. So when i got the idea to try to run the heavy simulation in an "extension" it was just a language i was a bit familiar with. Maybe C# would have been the "smarter" choice, i just never digged into it yet.

The other reason is that in my well closer circle i got quite some people that code c++ on a daily basis and i don't know (at least i think so) anyone doin C# actively, so i thought if i would get stuck i have people i can easily ask about my c++ problems.

So it wasn't a "i think c++ is better than c#" decision rather a what do i know and what resources i have available easily.

jdw64 8 hours ago

windsurfer 9 hours ago

C# is a "first class" language in Godot and doesn't need a GDExtension, but it's not compatible with web builds yet. There is a draft PR that includes C# support but it adds about +50 MB to a web export and is also missing a few features.

8-prime 7 hours ago

pjmlp 5 hours ago

pier25 6 hours ago

Not sure how relevant this is for this simulation use case but IIRC C# has a bigger overhead when communicating with the core engine compared to GDScript or C++.

momocowcow 11 hours ago

gdscript is incredibly slow, worst than something like lua, maybe only good for handling the UI events

the hierarchy and physics api isn’t great either, it’s easy to hit heap allocs even from a gdextension

a lot of things wrong with this generic engine, but at least it’s lightweight

Fraterkes 11 hours ago

Lots of things right too, thankfully

tancop 8 hours ago

Godot is only the best open source engine because Bevy is not ready for production, Lumberyard/O3DE is hard to set up and everything else is ancient or 2D only. one eyed man among the blind type shit

pier25 6 hours ago

tapoxi 5 hours ago

subhero 2 hours ago

jdw64 5 hours ago

stackghost 6 hours ago

droptablemain 5 hours ago

Assuming it's a 2D game, why not just use something like SFML to build your own simple RTS engine at that point?

Seems like carrying a lot of Godot baggage around for nothing.

omoikane 5 hours ago

Godot comes with a lot of tools in addition to the runtime. Maybe they are using the IDE to do layouts for the menu dialogues, for example.

Also, I am not sure about how easy it is to build binaries using SFML for various platforms (such as WASM), but with Godot you just have to download the right template.

valorzard 13 hours ago

If you know rust, the Godot rust bindings for GDExtension are also really good and let you use any Rust library in Godot (including tokio and async rust if you really want) https://godot-rust.github.io/

colechristensen 6 hours ago

I'm a big fan of the godot rust bindings as well

aquariusDue 11 hours ago

Came here to mention this. As an example there's godot-iroh which uses iroh for peer to peer networking:

https://github.com/tipragot/godot-iroh

fwsgonzo 13 hours ago

Just don't forget the versioning script needed on at least Linux. It's either that or build with the same older distro Godot uses, so you have a matching libstdc++ version. You can link with a newer stdlibc++ but you will need a linker versioning script that hides your impl from the dynamic linker so you don't get random ghosts in your machine.

czoido 12 hours ago

Hi! Yes, you are right, thanks for pointing this out. It's something to keep in mind when distributing an extension for Linux. I have just updated the post with a note about it.

MeteorMarc 12 hours ago

So, what profiling support is available to find the critical parts of your GDscript or C# code. Before needlessly jumping into c++ hassle for performance reasons? Tfa addresses functional reasons, which is ok.

Fraterkes 11 hours ago

For C# there’s basically nothing in engine, so you’d use Rider or Superluminal. Which is fine, Godot can have a bit too much nih imo

pjmlp 11 hours ago

I don't follow it that much, but I think there are no plans to improve GDscript performance other than maybe the interpreter itself, nothing with JIT or AOT in mind.

Also .NET integration has the issue it doesn't work in all target platforms, that is why Capcom and Unity have their own compilers to native code. Even when Unity finally adopts modern .NET, Native AOT naturally doesn't cover game consoles.

Rohansi 7 hours ago

It's too bad .NET AOT wouldn't support consoles. They use x86 and ARM processors that it already supports.

MindSpunk 5 hours ago

pjmlp 7 hours ago

irskep 5 hours ago

Coming from Instruments (Apple) and Chrome Dev Tools, I found the Godot profiler to be hilariously hard to get useful results out of because of its simplistic presentation of information that you can't drill down into.

jokoon 12 hours ago

So it requires writing a CMake script, some python, and some weird C++ code.

A bit tedious but that's how it goes.

OsrsNeedsf2P 12 hours ago

The point is that it's compatible, not that it's the recommended way of doing things.

Asmod4n 11 hours ago

I am building something similar, with c++26 reflection. So any language can use c++ libs with only a few lines of boilerplate in a lifetime and memory safe way where possible. And where it’s not possible to infer the safe lifetime of an object i got a small .toml file which tells the lib how to safely use those functions.

zerr 13 hours ago

> // Copy the position of every entity into the MultiMesh buffer

So, is a zero-copy impossible due to world (C++ vs Godot) boundaries?

czoido 12 hours ago

Hi! I don't think the boundary itself is the issue, although I'm not an expert on that part of Godot. My understanding is that the copy in this example comes from converting data from flecs into the layout MultiMesh expects. A different layout might reduce that work, but I haven't explored if fully zero-copy is possible.

TedDallas 5 hours ago

I’m using CPP with Godot for runtime procedural mesh generation. Works like a charm. It’s nice to have this option when you need it.

le-mark 11 hours ago

> Engine modules are compiled into the engine itself. They have full access to the internals, but you need to build and ship your own copy of Godot, including the editor and export templates for every platform.

I’m not familiar with distributing godot games. If I build a game to distribute on steam (for example) would this be an option? Or is a GDExtension (runtime loaded .so) the standard way to go?

warent 11 hours ago

It depends on what your use case is. GDExtension is the standard way to go, unless its API is too limited and you have to access/modify engine internals not otherwise exposed.

That being said, this has no impact on distribution either way as far as I know.

eole666 11 hours ago

GDExtension is the standard way. But building a custom version of Godot is common and won't be a problem for distributing the game on steam or any platform. It's necessary to build your own godot version and export templates to produce an encrypted build not too easily hackable for example.

hnacobsxph 12 hours ago

Static linking libstdc++ with -fvisibility=hidden saved me on Linux, though it bit me the day I needed exceptions to cross the boundary.

sylware 11 hours ago

c++ is sorta private to the application.

If the API is c++ based you have to statically link it to the engine since the chosen c++ runtime is statically linked to the engine binaries.

You cannot ship as a shared c++ runtime since it would conflict with a possible version installed on the user distro (version of the gcc libstdc++, version of the clang runtime, intel?, or none see below).

To avoid c++ ABI issues, distros may statically link their c++ runtimes (clang[c++ and compiler versions]/gcc[c++ and compiler and versions]/intel[c++ and compiler versions]/etc)... if they need any (and the new c++ to C transpiler may have some significant impact in the near future).

(BTW, is the c++ intel compiler still shipping??)

If the API is "C" based (aka core platform ABI), no issue, just statically load only the common glibc libs (ELF DT_NEED entries) and dynamically load (libdl/dlopen/dlsym/dlclose) everything else (private libs, or system interface shared libs), and you are good to ship. A word though: wayland code with its libxkbcommon are statically linked, do not reproduce the same mistakes than with x11).

This is required for broad distro support [and long term support].

Basically, game binaries should be "-static-libgcc -static-libstdc++ --enable-new-dtags" everywhere, statically load _ONLY_ common glibc libs (and with "old" symbol versions, see binutils ld documentation, the 2nd part of the VERSION documentation page), and dynamically load everything else.

I have been inspecting many recent godot4 games on steam: all had "correct" binaries to maximize broad distro loading support on the long run.

The current issues: some games are written in microsoft rust which toolchain is still unable to statically link libgcc (see tinyglade game). Or some unity versions which "forgot" the '-static-libgcc' compiling/linking options, and even forgot to statically link their libz Oo.

If valve could do just that with the binaries of their client and their games... They can keep their 'runtimes' for old broken games but should have 'correct' binaries for everything else on their side (and valve still has to port the final 32bits reaper command to 64bits for clean 64bits support, hopefully I did not miss other 32bits binaries). Forcing distros to compile that user namespace in their linux kernel is quite "inappropriate", better keep that optional for those broken games only.

ape4 9 hours ago

A big issue. If you can't ship a library its basically useless.

sylware 5 hours ago

If your API is c++ based, you ship a static lib. If the game engine is "closed" source, you also a have static lib (or a set of) for the game engine too, and "exporting" is actually linking (basically a binutils ld invokation). Ofc, you better use the same c++ compiler _VERSION_ than the game engine devs did use, or you are good for c++ hell.

If your API is C based (or core platform ABI), and you should design such API for interop with any framework anyway, you can ship a shared lib (but it has to statically load only the common glibc libs, and that with "old" symbol versions, and the other things too, see my previous post).