Gir.Core generates C# bindings for GTK and GStreamer from introspection data
A C# binding generator for GObject based libraries providing a C# friendly API surface
At a glance
- What is it?
- Gir.Core is a code generator that reads GObject Introspection repositories and emits C# for the GNOME stack, aiming for an API that mirrors the GObject concepts closely enough that you do not need reflection to use it. The README is candid about the gap to 1.0, listing overriding native virtual methods and custom interface implementations as still missing.
- Who is it for?
- Adopt Gir.Core if you want to write a Linux desktop application in C# against GTK 4 and GStreamer without hand-writing P/Invoke declarations, and if you can absorb API churn until 1.0. Do not adopt it if you need to override native virtual methods or implement native interfaces yourself, since the README lists both as missing, and do not expect the WebKit or JavaScriptCore bindings to work outside Linux.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the generator produces
Gir.Core provides C# bindings for several GObject based libraries like GTK for user interfaces, and the project aims to provide a complete set of APIs for writing rich cross-platform user interfaces and multimedia programs.
The mechanism is the well-established GObject Introspection framework for language bindings, and that choice is the whole architecture. GObject Introspection is a machine readable description of a library's classes, interfaces, methods, properties and signals, produced by the native library's own build. A binding generator reads that description and writes the foreign language wrapper.
The four stated features explain what the generator aims for rather than what it currently does. Deep integration means GirCore bridges the GObject type system with dotnet, and the design is close to the GObject concepts to allow a deep integration between both systems without using reflection. That last clause is the interesting one, because it is what distinguishes a generated binding from a reflection-based one: the types are known at compile time, so the C# compiler can check your calls and the JIT does not have to resolve them at run time.
Simplicity means memory management is handled automatically, which greatly simplifies the C-API, since the alternative in a raw interop scenario is manual reference counting on every object you keep.
Completeness means support for the entire GTK and GStreamer stack, enabling feature-rich applications which deeply integrate with the OS.
Extensibility means third party developers can write bindings for other GObject-based libraries, achieving full interoperability between them. That is what makes the project more than a set of GTK bindings, since the same generator can be pointed at a library nobody has written bindings for yet.
The project is C#, MIT licensed, with the site at gircore.github.io, the last push on 2026-10-16, and the releases 0.9.0-preview.1 from 2026-09-15, 0.8.1 from 2026-07-12 and 0.8.0 from 2026-06-25.
The status section is the honest part
Most binding projects hide this part, so it is worth reading the Status section closely.
The code is under active development and certain features may not be available. The API is subject to change as long as version 1.0 is not released. There are NuGet packages available, and the README points at the NuGet organisation for an overview.
Then there is a list of what you can generally expect to be available: creation of native structs and records, creation of native GObject based classes, creation of native enumerations, usage of native GObject based interfaces, reading and writing properties of native GObject based classes, receiving signals of native GObject based classes, and retaining state of purely managed GObject.Object based subclasses.
The last item is the one that tells you the generator does more than wrap native classes. Being able to subclass a GObject in pure C# and keep managed state in it is what makes it possible to write application code in C# rather than writing a small C shim for each custom widget.
And then the missing features, which is the part to plan around. Overriding of native virtual methods is not supported. Custom implementations of native GObject interfaces are not supported. And fundamental types like `GObject.Paramspec` or `Gtk.Expression` are only available in parts.
The first two are the ones that matter in practice. A GObject virtual method is the C-level equivalent of an overridable method, and in GTK the ones you are most likely to want to override are the drawing and measurement methods, and subclassing without being able to override a virtual method is a real constraint on what widgets you can build.
The README is also careful to qualify the list, saying it should not be considered complete as certain corner cases may not yet be listed, and inviting a bug report if you hit one. The upcoming features and releases are tracked in the project's milestones.
So the honest summary is a pre-1.0 generator with a broad surface and a specific list of holes, which is a usable position if you know your API surface in advance.
Which libraries it covers
The generated libraries table is the list of NuGet packages the project publishes, and it is broader than GTK alone.
GTK 4.0 is the UI toolkit and the centre of the set. Libadwaita 1 provides building blocks for modern GNOME applications, so the pair covers both the widget layer and the GNOME design language conventions on top of it. GStreamer 1.0 is the multimedia framework. Cairo 1.0 is the graphics library, and Pango 1.0 the font and text library.
Then the platform services. Gio 2.0 is the library for high level application functionality, which in practice means the file, process and notification APIs. GdkPixbuf 2.0 handles image loading in various formats. Secret 1 gives access to the system keyring via libsecret. Rsvg 2.0 is SVG rendering. GtkSource 5 extends a Gtk.TextView to be like a source code editor.
The last two entries carry a platform restriction worth noting. WebKit 6.0 is the browser engine and is marked Linux only, and JavaScriptCore 6.0, the JavaScript engine for WebKit, is also Linux only.
That restriction is worth understanding rather than treating as a footnote. WebKitGTK is a Linux and BSD project, and the browser engine on macOS is a different implementation entirely, so a binding for the macOS browser engine would be a different piece of work. The same applies to JavaScriptCore, where the Apple frameworks and the WebKitGTK build are separate implementations.
So the set is broad but the platform story is Linux-first, with the caveats that come from the underlying native libraries rather than from the generator.
Building the bindings yourself
Generating the bindings locally takes four commands, and there is one instruction that has to be followed exactly.
$ git clone --recursive https://github.com/gircore/gir.core.git
$ cd gir.core/scripts
$ dotnet fsi GenerateLibs.fsx
$ cd ../src
$ dotnet build GirCore.Libs.slnfThe `--recursive` flag on the clone is the instruction the README emphasises: make sure to initialise submodules with `--recursive` otherwise the `gir-files` directory will not be loaded properly. The introspection data is a submodule, pulled from the separate gircore/gir-files repository, and without it the generator has nothing to read.
The script is an F# script run with `dotnet fsi`, and it produces the generated sources, after which the solution filter `GirCore.Libs.slnf` is built. A solution filter rather than a full solution is used, so the build covers the libraries and not the samples and tests.
To clean the Libs folder of all generated files, you run another script from the scripts folder:
$ dotnet fsi CleanLibs.fsxFor more advanced build options the README points at the documentation page on building from source.
So the local build is a two-step process, generate and then build, and the generate step is the expensive one. For most users the NuGet packages make this unnecessary, but the local build is what you need if you are extending the generator to a library that has no published package.
How the code is organised
The repository structure tells you how the pipeline is split, and it is a good design.
Under `src/Generation` there are four projects. GirTool is the tool that generates the bindings, the entry point of the whole thing. GirLoader is a library for reading and resolving GObject Introspection repositories, so the parsing and the resolution of type references are separated from the emission of code. GirModel is an interface based definition of the GObject data model, used by the loader and the generator to have a common understanding of that model, which is the piece that lets the two halves evolve independently. And Generator is the code generator that produces C# code from GObject Introspection data.
That separation of model, loader and generator is the same shape as most modern code generators, and it is what makes the extensibility claim real: you can point the loader at a new introspection repository and the generator emits the same shape of C# without either half knowing about the specific library.
`src/Libs` contains manually written code for the libraries, and the generator outputs code there. `src/Samples` holds example programs using GTK, GStreamer and others, which is where you look to see how the generated API is meant to be used. `src/Integrations` holds source generators and source analyzers to simplify the GirCore usage, which is a nice touch: the same project can analyse your code to help you use the bindings correctly. `src/Tests` holds unit and integration tests.
There is one caveat the README states plainly: the code in the library folder is not complete because most of the code is generated when GirTool is run. So browsing `src/Libs` in a checkout tells you very little about what the API looks like, and the samples are the better guide.
The repository also carries `ext/` for the submodule, `docs/`, `img/`, `properties/`, `scripts/` and a `.gitmodules` file.
Where it fits against the alternatives
The alternative to a generated binding is usually one of three things, and each has a different cost.
The first is an existing binding for the same library. The README's link list includes GtkSharp, the long-standing C# binding for GTK, and Gir.Core is positioned against it rather than as a replacement for it in the same niche. The difference is generational: GtkSharp is listed among the project's links as a C# binding for GTK, while Gir.Core generates from current introspection data and aims at GTK 4 with the modern GNOME libraries around it.
The second is writing the interop by hand. For a small surface, a few P/Invoke declarations and a wrapper class are quicker than adopting a generator, and you end up with exactly the calls you need and no others. That approach scales badly, because each new widget or property is another declaration, and it puts the memory management on you.
The third is not using the native stack at all, which for a Linux desktop application is rarely realistic if you want to look native.
The case for Gir.Core is then fairly clear. It is for a C# developer who wants the GTK 4 and GStreamer stack without hand-writing interop, and who is willing to accept an API that is generated rather than designed, and to track a project whose surface will move until 1.0.
The limitations are the ones the Status section lists. Overriding native virtual methods is not supported, which constrains custom widgets that need custom drawing or measurement. Custom implementations of native GObject interfaces are not supported, which constrains code that wants to implement a callback interface from C#. Fundamental types like `GObject.Paramspec` and `Gtk.Expression` are only partly available, so anything built on those has gaps.
And the platform limits come from below: WebKit and JavaScriptCore are Linux only, so an application that has to run the same UI on macOS is not covered by this set of bindings.
Editorial conclusion
Adopt Gir.Core if you want to write a Linux desktop application in C# against GTK 4 and GStreamer without hand-writing P/Invoke declarations, and if you can absorb API churn until 1.0. Do not adopt it if you need to override native virtual methods or implement native interfaces yourself, since the README lists both as missing, and do not expect the WebKit or JavaScriptCore bindings to work outside Linux. Verify first that the library you need is in the generated list, that you build with `--recursive` so the introspection files are present, that you pin a package version rather than tracking the pre-release line, and that you have read the unsupported feature list for your own case, since the README says it is not complete.
Frequently asked questions
What is Gir.Core?
It provides C# bindings for several GObject based libraries like GTK for user interfaces, built on the GObject Introspection framework for language bindings. The project aims to provide a complete set of APIs for writing cross-platform user interfaces and multimedia programs in C#.
Which libraries does Gir.Core generate bindings for?
GTK 4.0 for the UI toolkit, Libadwaita 1 for modern GNOME building blocks, GStreamer 1.0 for multimedia, Cairo 1.0, Pango 1.0, Gio 2.0, GdkPixbuf 2.0, GtkSource 5, Secret 1 for the system keyring and Rsvg 2.0. WebKit 6.0 and JavaScriptCore 6.0 are Linux only.
Is Gir.Core ready for production use?
The README states that the code is under active development, that certain features may not be available, and that the API is subject to change as long as version 1.0 is not released. NuGet packages are available, and the upcoming work is tracked in the project milestones.
What does Gir.Core not support yet?
The README lists overriding of native virtual methods, custom implementations of native GObject interfaces, and fundamental types like GObject.Paramspec or Gtk.Expression being only available in parts. It also warns that the list of unsupported features should not be considered complete.
How do I build the Gir.Core bindings locally?
Clone with `git clone --recursive` so the gir-files submodule is loaded, then run `dotnet fsi GenerateLibs.fsx` from the scripts directory and `dotnet build GirCore.Libs.slnf` from the src directory. The Libs folder can be cleared of generated files with `dotnet fsi CleanLibs.fsx`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gircore-gir-core)Was this useful?