{"slug": "using-any-c-library-in-godot", "title": "Using any C++ library in Godot", "summary": "ConanCenter now hosts godot-cpp 10, the official C++ bindings for the Godot game engine, enabling developers to bring any C or C++ library into a Godot project through GDExtension. The Conan blog post demonstrates the workflow by integrating the flecs Entity Component System library to simulate 100,000 particles inside a Godot scene, noting that godot-cpp must match the Godot version and each added library must be compiled for every target platform. GDExtension loads a shared library (.dll, .so, .dylib, or .wasm on the web) into an unmodified Godot build at runtime through a stable C interface, and classes exposed this way appear in the editor alongside built-in nodes and are usable from GDScript.", "body_md": "[< Back to the blog](https://blog.conan.io)\n\n# Using any C++ library in Godot\n\n[Godot](https://godotengine.org/) has become one of the most popular game\nengines of the last few years. It is free, open source under the MIT license,\nand small enough to download and start using in minutes. Most Godot games are\nwritten in GDScript, the engine’s own scripting language.\n\nSooner or later, though, many projects need something that already exists as\na C or C++ library: a simulation library, a database, a networking protocol,\na machine learning runtime. GDScript cannot call native code, but Godot can\nload it through **GDExtension**, and **godot-cpp**, the official C++\nbindings, lets you expose that code as regular engine classes. Writing the\nC++ code is the easy part. The hard part is the build: godot-cpp has to match\nyour Godot version, and every library you add has to be compiled for each\nplatform you ship to.\n\nIn this post we give a short tour of Godot, explain how C++ extensions work,\nand show how to bring C++ libraries into a Godot game with Conan and\ngodot-cpp 10, now available in ConanCenter. As an example we\nwill use [flecs](https://github.com/SanderMertens/flecs), an Entity\nComponent System library, to simulate 100,000 particles inside a Godot scene.\n\n## A Quick Introduction to Godot\n\nGodot is a general purpose engine for 2D and 3D games. Everything in a Godot project is built from two concepts:\n\n- **Nodes** are the basic building blocks. Each node has a type (`Sprite2D` ,`Camera3D` ,`AudioStreamPlayer` ,`Timer` …), a set of properties you can\nedit in the Inspector, and callbacks such as`_ready()` or`_process()` that\nthe engine calls during the game loop.\n- **Scenes** are trees of nodes saved to disk as`.tscn` files. A scene can be\na character, a menu or a whole level, and scenes can be instanced inside\nother scenes.\n\nBehavior is usually added by attaching a script to a node. GDScript is a Python-like language designed for the engine, and it is great for gameplay logic because changes show up immediately without a compile step.\n\nWhat makes Godot interesting for C++ developers is that the engine itself is written in C++, and it can load extensions written in C++ without being recompiled. A class that comes from one of these extensions becomes a regular engine class: it shows up in the editor next to the built-in nodes, with its properties in the Inspector, and GDScript can use it like any other node. The next section explains how these extensions work.\n\n## Extending Godot with C++\n\nThere are two ways to add C++ code to Godot:\n\n- **[Engine\nmodules](https://docs.godotengine.org/en/stable/engine_details/engine_api/custom_modules_in_cpp.html)** are compiled into the engine itself. They have full access to the\ninternals, but you need to build and ship your own copy of Godot, including\nthe editor and export templates for every platform.\n- **[GDExtension](https://docs.godotengine.org/en/stable/engine_details/engine_api/gdextension/what_is_gdextension.html)** loads a shared library (`.dll` ,`.so` ,`.dylib` , or`.wasm` on the web) into\nan official, unmodified Godot build at runtime. The engine talks to the\nlibrary through a stable C interface.\n\nGDExtension is the recommended approach for most projects, and it is how many\npopular plugins are distributed today. Because the C interface is verbose to\nuse directly, the Godot team maintains\n[godot-cpp](https://github.com/godotengine/godot-cpp), a C++ library that\nwraps it with an API very close to the one used inside the engine. It provides\na C++ class for every engine class, such as `Node2D`, `Sprite2D` or `Input`.\n\nYour own classes are regular C++ code that derives from those classes. A node written with godot-cpp looks like this:\n\n```\n#include <godot_cpp/classes/node2d.hpp>\n\nnamespace godot {\n\nclass MyNode : public Node2D {\n    GDCLASS(MyNode, Node2D)\n\nprotected:\n    static void _bind_methods() {}\n\npublic:\n    void _process(double p_delta) override {\n        // runs every frame\n    }\n};\n\n} // namespace godot\n```\n\nSince version 10.0, a single godot-cpp release works with any Godot version\nfrom 4.3 onwards. You pick one with the `api_version` build option, and\ngodot-cpp generates its C++ classes from the API of that version. An\nextension built for Godot 4.3 also works in newer versions, but not in older\nones, so you usually pick the oldest Godot version you want to support.\n\n### Build targets and feature tags\n\nThere is one more concept you need to know before building anything.\ngodot-cpp is compiled for one of three **targets**, named after the Godot\nbuilds that load the library:\n\n- `template_debug` : the default. Enables debug checks through the`DEBUG_ENABLED` definition. This library is loaded by the editor and by\ndebug exports.\n- `template_release` : for release exports, with the debug checks removed.\n- `editor` : for libraries that are only loaded by the editor.\n\nWhich library Godot loads is decided at runtime by a small `.gdextension`\nfile. It maps **feature tags** to library paths. The `debug` tag matches the\neditor and debug exports, and the `release` tag matches release exports:\n\n```\n[configuration]\nentry_symbol = \"gdexample_library_init\"\ncompatibility_minimum = \"4.7\"\n\n[libraries]\nmacos.debug = \"res://bin/libgdexample.template_debug.dylib\"\nmacos.release = \"res://bin/libgdexample.template_release.dylib\"\nlinux.debug = \"res://bin/libgdexample.template_debug.so\"\nlinux.release = \"res://bin/libgdexample.template_release.so\"\nwindows.debug = \"res://bin/libgdexample.template_debug.dll\"\nwindows.release = \"res://bin/libgdexample.template_release.dll\"\n```\n\n### The usual workflow\n\nThe [Godot\ndocumentation](https://docs.godotengine.org/en/stable/tutorials/scripting/cpp/gdextension_cpp_example.html)\nrecommends adding godot-cpp to your repository as a git submodule and\nbuilding it together with your library using SCons. That works well for a\nfirst extension, but every project ends up compiling its own godot-cpp for\neach target, platform and architecture, and any third party library you\nwrap, such as a physics engine or a machine learning runtime, has to be\nvendored and built with matching flags for every platform Godot exports to.\n\nBoth are exactly the kind of problem Conan was built to solve.\n\n## Managing the Dependencies with Conan\n\nWith the godot-cpp recipe in ConanCenter, godot-cpp becomes a regular package. The two parameters discussed above are Conan options:\n\n- `api_version` : the Godot API version the bindings target, from`4.3` to`4.7` (the default).\n- `target` :`template_debug` (the default),`template_release` or`editor` .\n\nEach combination is built once and then reused by every project that needs it, instead of being compiled inside each extension.\n\nYour GDExtension becomes just another C++ project with dependencies. Any of\nthe more than 1,900 libraries in [ConanCenter](https://conan.io/center), or\none you package yourself with a [Conan\nrecipe](https://docs.conan.io/2/tutorial/creating_packages.html), can be\nadded next to godot-cpp, and Conan builds all of them consistently for every\nplatform you target.\n\n## A Practical Example: A Swarm of 100,000 Particles\n\nTo show how this works in practice, we will write a GDExtension that\nregisters a new `Swarm` node. It simulates 100,000 particles that flee from\nthe mouse cursor and bounce off the window edges, and draws all of them in a\nGodot scene.\n\nThe simulation runs on [flecs](https://github.com/SanderMertens/flecs), an\n**Entity Component System (ECS)** library for C and C++. In an ECS, entities\nare plain ids, components are plain data structs attached to them, and\nsystems are functions that run over every entity that has a given set of\ncomponents. Components of the same type are stored together in memory, which\nmakes iterating over large numbers of entities very fast. That is why ECS is\na popular choice for simulations, crowds or bullet hell games. It is also\nthe kind of work where native code pays off, since updating this many\nentities every frame is much faster in C++ than in GDScript.\n\nYou can find the complete example in the [Conan examples2\nrepository](https://github.com/conan-io/examples2/tree/main/examples/libraries/godot-cpp/gdextension):\n\n``` bash\n$ git clone https://github.com/conan-io/examples2.git\n$ cd examples2/examples/libraries/godot-cpp/gdextension\n```\n\nThe `src` folder contains the extension code, and `demo` is a regular Godot\nproject that loads it.\n\n### Declaring the dependencies\n\nThe `conanfile.py` requires `godot-cpp` and `flecs` from ConanCenter:\n\n``` python\nfrom conan import ConanFile\nfrom conan.tools.cmake import CMake, CMakeToolchain, cmake_layout\n\nclass GDExtensionExample(ConanFile):\n    package_type = \"shared-library\"\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"CMakeDeps\"\n\n    def requirements(self):\n        self.requires(\"godot-cpp/10.0.0\")\n        self.requires(\"flecs/4.1.6\")\n\n    def layout(self):\n        cmake_layout(self)\n\n    def generate(self):\n        tc = CMakeToolchain(self)\n        # Godot picks the library to load by its build \"target\", so we name\n        # the output after the target godot-cpp was built with\n        tc.cache_variables[\"GODOTCPP_TARGET\"] = str(self.dependencies[\"godot-cpp\"].options.target)\n        tc.generate()\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n```\n\nThe only Godot specific detail is in `generate()`. We read the `target`\noption of the godot-cpp dependency and pass it to CMake, so the name of the\nlibrary always matches the godot-cpp binary it was linked against.\n\n### The CMakeLists.txt\n\n```\ncmake_minimum_required(VERSION 3.15)\nproject(gdexample LANGUAGES CXX)\n\nfind_package(godot-cpp REQUIRED CONFIG)\nfind_package(flecs REQUIRED CONFIG)\n\nadd_library(gdexample SHARED\n    src/register_types.cpp\n    src/swarm.cpp\n)\ntarget_link_libraries(gdexample PRIVATE godot-cpp flecs::flecs_static)\n\n# Output as demo/bin/libgdexample.<target>.<ext>, the path the\n# demo/bin/gdexample.gdextension file points Godot to. The generator\n# expression prevents multi-config generators from adding a Release/ subfolder\nset_target_properties(gdexample PROPERTIES\n    OUTPUT_NAME \"gdexample.${GODOTCPP_TARGET}\"\n    PREFIX \"lib\"\n    LIBRARY_OUTPUT_DIRECTORY \"$<1:${CMAKE_SOURCE_DIR}/demo/bin>\"\n    RUNTIME_OUTPUT_DIRECTORY \"$<1:${CMAKE_SOURCE_DIR}/demo/bin>\"\n)\n```\n\nThis is a completely standard CMake project. The extension is a shared\nlibrary that links godot-cpp and flecs statically, so there is a single\nlibrary file to ship. We write it straight into `demo/bin` so Godot finds it\nwithout an extra copy step.\n\n### Writing the node\n\nThe `Swarm` class derives from `Node2D` and owns the flecs world. The\ncomponents of each particle are plain structs. The `GDCLASS` macro adds the\nboilerplate that Godot’s class system needs, and `_bind_methods()` declares\nwhat Godot can see, in this case the `count` and `flee_radius` properties.\nOnce the class is registered, they appear in the Inspector and can be used\nfrom GDScript. This is a simplified view of the class:\n\n```\nstruct Position { float x, y; };\nstruct Velocity { float x, y; };\n\nclass Swarm : public Node2D {\n    GDCLASS(Swarm, Node2D)\n\n    int count = 100000;\n    double flee_radius = 150.0;\n    flecs::world world;\n    ...\n\nprotected:\n    static void _bind_methods() {\n        ClassDB::bind_method(D_METHOD(\"set_count\", \"count\"), &Swarm::set_count);\n        ClassDB::bind_method(D_METHOD(\"get_count\"), &Swarm::get_count);\n        ADD_PROPERTY(PropertyInfo(Variant::INT, \"count\"), \"set_count\", \"get_count\");\n        // ... and the same for flee_radius\n    }\n    ...\n};\n```\n\nThe rest of the node connects both worlds. `_ready()` creates one flecs\nentity per particle and a flecs system that updates them. It also sets up a\n[MultiMesh](https://docs.godotengine.org/en/stable/classes/class_multimesh.html),\nwhich draws many instances of the same mesh in a single draw call, because\none Godot node per particle would be far too heavy for 100,000 of them.\n\nEvery frame, `_process()` hands the mouse position to flecs, runs the systems\nwith `world.progress()`, and copies the resulting positions back into the\nMultiMesh. Again, this is a simplified view, and the full code is in the\nrepository:\n\n```\nvoid Swarm::_ready() {\n    // One entity per particle, with a Position and a Velocity component\n    for (int i = 0; i < count; i++) {\n        world.entity().set<Position>({ ... }).set<Velocity>({ ... });\n    }\n\n    // A system that runs for every entity with both components\n    world.system<Position, Velocity>(\"Move\").each([this](flecs::iter &it, size_t, Position &p, Velocity &v) {\n        // flee from the mouse, move, and bounce off the window edges\n    });\n\n    // A MultiMeshInstance2D child node that draws all the particles\n    ...\n}\n\nvoid Swarm::_process(double p_delta) {\n    mouse = get_local_mouse_position();\n    world.progress(static_cast<float>(p_delta));\n\n    // Copy the position of every entity into the MultiMesh buffer\n    render_query.each([&](const Position &p, const Velocity &v) { ... });\n    multimesh->set_buffer(buffer);\n}\n```\n\n### Registering the extension\n\nFinally, `register_types.cpp` registers the class when Godot loads the\nlibrary:\n\n```\nvoid initialize_gdexample_module(ModuleInitializationLevel p_level) {\n    if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {\n        return;\n    }\n    GDREGISTER_RUNTIME_CLASS(Swarm);\n}\n```\n\nWe register `Swarm` with `GDREGISTER_RUNTIME_CLASS`. By default, the code of\na GDExtension class also runs inside the editor, so `_ready()` and\n`_process()` would start the simulation while you are editing the scene. A\n**runtime class** is only a placeholder in the editor: you can add it to a\nscene and set its properties, but its code only runs when the game is\nrunning.\n\nThe same file defines `gdexample_library_init()`, the entry point named in\nthe `.gdextension` file. It is a few lines of boilerplate that look the same\nin every extension.\n\n### Building and running\n\nWith everything in place, building the extension is a single command:\n\n``` bash\n$ conan build . --build=missing\n...\n[100%] Linking CXX shared library .../demo/bin/libgdexample.template_debug.dylib\n[100%] Built target gdexample\n```\n\nConan resolves godot-cpp and flecs, downloads precompiled binaries from ConanCenter when they exist for your configuration, builds the rest from source, generates the CMake integration and finally builds the extension.\n\n**Note:** godot-cpp requires C++17. If your default profile uses an older\nstandard, which is the case for MSVC, add `-s compiler.cppstd=17` to the\ncommand.\n\nNow start Godot 4.7, click “Import” in the Project Manager, and select\n`demo/project.godot`. When the project opens, Godot reads\n`bin/gdexample.gdextension`, loads the library, and `Swarm` becomes available\nlike any built-in node. You can find it in the “Create New Node” dialog,\nunder `Node2D`:\n\nThe main scene of the demo already contains a `Swarm` node. Selecting it\nshows `count` and `flee_radius` in the Inspector, the two properties we bound\nin `_bind_methods()`:\n\nPress Play to run the scene, and move the mouse over the window to push the\nparticles around. Then stop it, change `count` or `flee_radius` in the\nInspector, and play it again to see how the swarm behaves with more particles\nor a wider flee radius.\n\n## Conclusion\n\nGDExtension and godot-cpp let you write engine classes in C++, and Conan takes care of building godot-cpp and any other C++ library your extension needs. This is also a big advantage when you distribute the extension: building it for every platform you ship to only takes changing the settings of the build.\n\nTry the [complete\nexample](https://github.com/conan-io/examples2/tree/main/examples/libraries/godot-cpp/gdextension)\nand check the [godot-cpp documentation](https://docs.godotengine.org/en/stable/tutorials/scripting/cpp/about_godot_cpp.html)\nto learn more about writing extensions. If you have any feedback or run into\nany issues, please let us know in the [Conan GitHub\nrepository](https://github.com/conan-io/conan/issues).\n\nHappy game development!\n\n*This post was written with AI assistance and reviewed by humans.*", "url": "https://wpnews.pro/news/using-any-c-library-in-godot", "canonical_source": "https://blog.conan.io/cpp/conan/gamedev/godot/cmake/2026/09/29/Using-Any-Cpp-Library-In-Godot.html", "published_at": "2026-09-29 08:40:37+00:00", "updated_at": "2026-09-29 08:48:21.062357+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Godot", "godot-cpp", "Conan", "ConanCenter", "flecs", "GDExtension", "GDScript"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/using-any-c-library-in-godot", "markdown": "https://wpnews.pro/news/using-any-c-library-in-godot.md", "text": "https://wpnews.pro/news/using-any-c-library-in-godot.txt", "jsonld": "https://wpnews.pro/news/using-any-c-library-in-godot.jsonld"}}