{"id":26070019,"url":"https://github.com/rcalixte/libqt6zig","last_synced_at":"2025-04-11T18:50:52.503Z","repository":{"id":281244767,"uuid":"944500364","full_name":"rcalixte/libqt6zig","owner":"rcalixte","description":"Qt 6 for Zig","archived":false,"fork":false,"pushed_at":"2025-03-30T20:42:18.000Z","size":5533,"stargazers_count":33,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-30T21:21:31.448Z","etag":null,"topics":["bindings","gui-library","qt","qt6","zig","zig-package","ziglang"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rcalixte.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-07T13:05:40.000Z","updated_at":"2025-03-28T05:23:55.000Z","dependencies_parsed_at":"2025-03-30T21:30:57.320Z","dependency_job_id":null,"html_url":"https://github.com/rcalixte/libqt6zig","commit_stats":null,"previous_names":["rcalixte/libqt6zig"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcalixte%2Flibqt6zig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcalixte%2Flibqt6zig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcalixte%2Flibqt6zig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcalixte%2Flibqt6zig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rcalixte","download_url":"https://codeload.github.com/rcalixte/libqt6zig/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248464098,"owners_count":21108213,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bindings","gui-library","qt","qt6","zig","zig-package","ziglang"],"created_at":"2025-03-08T23:07:00.892Z","updated_at":"2025-04-11T18:50:52.492Z","avatar_url":"https://github.com/rcalixte.png","language":"Zig","funding_links":[],"categories":["Libraries","Multimedia \u0026 Graphics"],"sub_categories":["GUI"],"readme":"\u003cdiv align=\"center\"\u003e\n\u003cimg alt=\"libqt6zig\" src=\"assets/libqt6zig.png\" height=\"128px;\" /\u003e\n\n![MIT License](https://img.shields.io/badge/License-MIT-green)\n[![Go Report Card](https://goreportcard.com/badge/github.com/rcalixte/libqt6zig)](https://goreportcard.com/report/github.com/rcalixte/libqt6zig)\n[![Static Badge](https://img.shields.io/badge/v0.14%20(stable)-f7a41d?logo=zig\u0026logoColor=f7a41d\u0026label=Zig)](https://ziglang.org/download/)\n\u003c/div\u003e\n\n---\n\nMIT-licensed Qt 6 bindings for Zig\n\nThis library is a straightforward binding of the Qt 6.4+ API. You must have a working Qt 6 C++ development toolchain to use this binding. The [Building](#building) section below has instructions for installing the required dependencies.\n\nThis library is designed to be used as a dependency in a larger application and not as a standalone library. The versioning scheme used by this library is based on the Qt version used to generate the bindings with an additional nod to the library revision number. Any breaking changes to the library will be reflected in the changelog.\n\nThese bindings are based on the [MIQT bindings for Go](https://github.com/mappu/miqt) that were released in 2024. The bindings are complete for QtCore, QtGui, QtWidgets, QtCharts, QtMultimedia, QtMultimediaWidgets, QtNetwork, QtPrintSupport, QtSpatialAudio, QtSvg, QtWebChannel, QtWebEngine, QScintilla, and others. There is support for slots/signals, subclassing, custom widgets, async via Qt, etc., but the bindings may be immature or unstable in some ways. It is fairly easy to encounter segmentation faults with improper handling. Q3 of the [FAQ](#faq) is a decent entry point for newcomers. Please try out the library and start a [discussion](https://github.com/rcalixte/libqt6zig/discussions) if you have any questions or issues relevant to this library.\n\n---\n\nTABLE OF CONTENTS\n-----------------\n\n- [Supported Platforms](#supported-platforms)\n- [License](#license)\n- [Examples](#examples)\n- [Building](#building)\n- [Usage](#usage)\n- [FAQ](#faq)\n- [Special Thanks](#special-thanks)\n\nSupported platforms\n-------------------\n\n| OS      | Arch   | Linkage (Bindings) | Status  |\n| ------- | ------ | ------------------ | ------- |\n| FreeBSD | x86_64 | Static             | ✅ Works |\n| Linux   | arm64  | Static             | ✅ Works |\n| Linux   | x86_64 | Static             | ✅ Works |\n\nLicense\n-------\n\nThe `libqt6zig` bindings are licensed under the MIT license.\n\nYou must also meet your Qt license obligations.\n\nExamples\n--------\n\nThe [`helloworld`](https://github.com/rcalixte/libqt6zig-examples/tree/master/src/helloworld/main.zig) example follows:\n\n```zig\nconst std = @import(\"std\");\nconst qt6 = @import(\"libqt6zig\");\nconst qapplication = qt6.qapplication;\nconst qpushbutton = qt6.qpushbutton;\nconst qwidget = qt6.qwidget;\n\nvar counter: isize = 0;\n\npub fn main() void {\n    // Initialize Qt application\n    const argc = std.os.argv.len;\n    const argv = std.os.argv.ptr;\n    _ = qapplication.New(argc, argv);\n\n    const text = \"Hello world!\";\n    const widget = qwidget.New2();\n    if (widget == null) @panic(\"Failed to create widget\");\n    defer qwidget.QDelete(widget);\n\n    // We don't need to free the button, it's a child of the widget\n    const button = qpushbutton.New5(text, widget);\n    qpushbutton.SetFixedWidth(button, 320);\n\n    qpushbutton.OnClicked(button, button_callback);\n\n    qwidget.Show(widget);\n\n    _ = qapplication.Exec();\n\n    std.debug.print(\"OK!\\n\", .{});\n}\n\nfn button_callback(self: ?*anyopaque) callconv(.c) void {\n    counter += 1;\n    var buffer: [64]u8 = undefined;\n    const text = \"You have clicked the button {} time(s)\";\n    const formatted = std.fmt.bufPrintZ(\u0026buffer, text, .{counter}) catch @panic(\"Failed to bufPrintZ\");\n    qpushbutton.SetText(self, formatted);\n}\n```\n\nFull examples are available in the [`libqt6zig-examples`](https://github.com/rcalixte/libqt6zig-examples) repository.\n\nBuilding\n--------\n\nFreeBSD (native)\n----------------\n\n- *Tested with FreeBSD 14 / Qt 6.8*\n\nFor dynamic linking with the Qt 6 system libraries:\n\n```bash\nsudo pkg install qt6-base qt6-charts qt6-multimedia qt6-svg qt6-webchannel qt6-webengine qscintilla2-qt6 zig\n```\n\n\u003e [!NOTE]\n\u003e The `zig` package may need to be downloaded or compiled and installed separately if the latest stable version is not available in the default repositories.\n\nLinux (native)\n--------------\n\n- *Tested with Debian 12 + 13 / Qt 6.4 + 6.8*\n\n- *Tested with Linux Mint 22 / Qt 6.4*\n\n- *Tested with Ubuntu 24.04 / Qt 6.4*\n\n- *Tested with Fedora 41 / Qt 6.8*\n\n- *Tested with EndeavourOS Mercury / Qt 6.8*\n\nFor dynamic linking with the Qt 6 system libraries:\n\n- __Debian-based distributions__:\n\n```bash\nsudo apt install qt6-base-dev libqscintilla2-qt6-dev qt6-base-private-dev qt6-charts-dev qt6-multimedia-dev qt6-svg-dev qt6-webchannel-dev qt6-webengine-dev\n```\n\n\u003e [!NOTE]\n\u003e The `zig` package must be downloaded and installed separately.\n\n- __Fedora-based distributions__:\n\n```bash\nsudo dnf install qt6-qtbase-devel qscintilla-qt6-devel qt6-qtcharts-devel qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qtwebchannel-devel qt6-qtwebengine-devel zig\n```\n\n\u003e [!NOTE]\n\u003e The `zig` package will need to be downloaded and installed separately if the latest stable version is not available in the default repositories.\n\n- __Arch-based distributions__:\n\n```bash\nsudo pacman -S qt6-base qscintilla-qt6 qt6-charts qt6-multimedia qt6-svg qt6-webchannel qt6-webengine zig\n```\n\nOnce the required packages are installed, the library can be built from the root of the repository:\n\n```bash\nzig build\n```\n\nUsers of Arch-based distributions need to __make sure that all packages are up-to-date__ first and will need to add the following option to support successful compilation:\n\n```bash\nzig build -Denable-workaround=true\n```\n\nThe compiled libraries can be installed to the system in a non-default location by adding the `--prefix-lib-dir` option to the build command:\n\n```bash\nsudo zig build --prefix-lib-dir /usr/local/lib/libqt6zig # creates /usr/local/lib/libqt6zig/{libraries}\n```\n\nTo skip the restricted extras:\n\n```bash\nzig build -Dskip-restricted=true\n```\n\nTo see the full list of build options available:\n\n```bash\nzig build --help\n```\n\nUsage\n-----\n\n- Import the library into your project:\n\n```bash\nzig fetch --save git+https://github.com/rcalixte/libqt6zig\n```\n\nAppend `#\u003ctag\u003e`, `#\u003ccommit\u003e`, or `#\u003cbranch\u003e` to the end of the URL to pin to a specific version of the library.\n\n- Add the library to your `build.zig` file:\n\n```zig\nconst qt6zig = b.dependency(\"libqt6zig\", .{\n    .target = target,\n    .optimize = .ReleaseFast,\n});\n\n// After defining the executable, add the module from the library\nexe.root_module.addImport(\"libqt6zig\", qt6zig.module(\"libqt6zig\"));\n\n// Link the compiled libqt6zing libraries to the executable\n// qt_lib_name is the name of the target library without prefix and suffix, e.g. qapplication, qwidget, etc.\nexe.root_module.linkLibrary(qt6zig.artifact(qt_lib_name));\n```\n\n__Extra options are required for building on Arch-based distributions. Refer to the build system at the examples link below for more details.__\n\n- Use the library in your code:\n\n```zig\n// the main qt6 module to import\nconst qt6 = @import(\"libqt6zig\");\n\n// C ABI Qt typedefs (if needed)\nconst C = qt6.C;\n\n// Qt class imports for Zig\nconst qapplication = qt6.qapplication;\nconst qwidget = qt6.qwidget;\nconst qnamespace_enums = qt6.qnamespace_enums;\n```\n\nFull examples of the build system and sample applications can be found in the [`libqt6zig-examples`](https://github.com/rcalixte/libqt6zig-examples) repository. Cross-compilation is not supported by this library at this time.\n\nFAQ\n---\n\n### Q1. Can I release a proprietary, commercial app with this binding?\n\nYes. You must also meet your Qt license obligations: either dynamically link Qt library files under the LGPL or purchase a Qt commercial license for static linking.\n\n### Q2. How long does it take to compile?\n\nUnder normal conditions, the first compilation of the entire library should take less than 10 minutes, assuming the hardware in use is at or above the level of that of a consumer-grade mid-tier machine released in the past decade. Once the build cache is warmed up, subsequent compilations should be very fast, on the order of seconds. For client applications that use and configure a specific subset of the main library, the expected compilation time should be much shorter, e.g. compiling the `helloworld` example, only linking the libraries needed and without a warm cache, should take under 30 seconds.\n\n### Q3. How does the `libqt6zig` API differ from the official Qt C++ API?\n\nSupported Qt C++ class methods are implemented 1:1 as structs of functions where the function names in Zig correspond to the PascalCase equivalent of the Qt C++ method and the struct names are lowercase equivalents of the Qt C++ class name. [The official Qt documentation](https://doc.qt.io/qt-6/classes.html) should be used for reference and is included in the library wrapper source code (though not all links are guaranteed to work perfectly, nor is this functionality in scope for this project).\n\n- `QWidget::show()` is projected as `qwidget.Show(?*anyopaque)`\n- `QPushButton::setText(QString)` is projected as `qpushbutton.SetText(?*anyopaque, []const u8)`\n\nAs a mental model, developers consuming this library should keep in mind that there are essentially two different tracks of memory management required for clean operation: one for the C++ side and one for the Zig side. The Zig side is managed by the developer and the C++ side has variant ownership semantics. Ownership semantics are documented throughout the [C++ documentation](https://doc.qt.io/qt-6/topics-core.html).\n\nThere are bits of idiomatic Zig in the library in the form of allocators as parameters to functions but much of the code is not idiomatic for Zig due to the complexity of the Qt C++ API. Knowledge of the Qt C++ API is required to understand and make full use of the library. While not an exhaustive list, there are some key topics to understand:\n\n- [Qt object ownership](https://doc.qt.io/qt-6/objecttrees.html)\n- [Qt signals and slots](https://doc.qt.io/qt-6/signalsandslots.html)\n- [Qt's property system](https://doc.qt.io/qt-6/properties.html)\n- [Qt's Meta-Object system](https://doc.qt.io/qt-6/metaobjects.html)\n- [Qt widgets](https://doc.qt.io/qt-6/examples-widgets.html)\n\nThe `QByteArray`, `QString`, `QList\u003cT\u003e`, `QVector\u003cT\u003e`, `QMap\u003cK,V\u003e`, `QHash\u003cK,V\u003e` types are projected as plain Zig types: `[]u8`, `[]const u8`, `[]T`, `AutoHashMapUnmanaged[K]V`, and `StringHashMapUnmanaged[V]`. Therefore, it is not possible to call any of the Qt type's methods and some Zig equivalent method must be used instead. (The raw C ABI is also available due to the headers being required to define Qt types in Zig, but it is not recommended for use beyond Qt class type definitions where needed.) This library was constructed with the goal of enabling single-language application development. Anything beyond that boundary is up to the developer to implement.\n\n- Zig string types are internally converted to `QString` using `QString::fromUtf8`. Therefore, the Zig string input must be UTF-8 to avoid [mojibake](https://en.wikipedia.org/wiki/Mojibake). If the Zig input string contains binary data, the conversion would corrupt such bytes into U+FFFD (�). On return to Zig space, this becomes `\\xEF\\xBF\\xBD`.\n\n- The iteration order of a Qt `QMap`/`QHash` will differ from the Zig API map iteration order. `QMap` is iterated by key order, but the Zig maps used by the library and `QHash` iterate in an undefined internal order. Future versions of `libqt6zig` may provide a way to iterate in a specific order.\n\nThere is a helper library that contains some types and functions that are useful for the C ABI but these are not required for the Zig API.\n\nWhere Qt returns a C++ object by value (e.g. `QSize`), the binding may have moved it to the heap, and in Zig, this may be represented as a pointer type. In such cases, the caller is the owner and must free the object (using either `QDelete` methods for the type or deallocating or destroying via the allocators). This means code using `libqt6zig` can look similar to the Qt C++ equivalent code but with the addition of proper memory management.\n\nThe `connect(targetObject, targetSlot)` methods are projected as `On(targetObject, fn() callconv(.c)...)`. While the parameters in the methods themselves are more convenient to use, the documentation comments in the Zig source code should be used for reference for the proper usage of the parameter types and Qt vtable references. The example code above includes a simple callback function that can be used as a reference.\n\n- You can also override virtual methods like `PaintEvent` in the same way. Where supported, there are additional `On` and `QBase` variants:\n  - `OnPaintEvent`: Set an override callback function to be called when `PaintEvent` is invoked. For certain methods, even with the override set, the base class implementation can still be called by Qt internally and these calls can not be prevented.\n  - `QBasePaintEvent`: Invoke the base class implementation of `PaintEvent`. This is useful for when the custom implementation requires the base class implementation. (When there is no override set, the `QBase` implementation is equivalent to `PaintEvent`.)\n\nQt class inherited types are projected via opaque pointers and `@ptrCast` in Zig. For example, to pass a `var myLabel: ?*QLabel` to a function taking only the `?*QWidget` base class, it should be sufficient to pass `myLabel` and the library will automatically cast it to the correct type and Qt vtable reference.\n\n- When a Qt subclass adds a method overload (e.g. `QMenu::sizeHint(QMenu*)` vs `QWidget::sizeHint(QWidget*)`), the base class version is shadowed and can only be called via `qwidget.SizeHint(?*anyopaque)` while the subclass implementation can be called directly, e.g. `qmenu.SizeHint(?*anyopaque)`. Inherited methods are shadowed for convenience as well, e.g. `qmenu.Show(?*anyopaque)` is equivalent to `qwidget.Show(?*anyopaque)`. While the library aims to simplify usage, consideration should still be given to the Qt documentation for the proper usage of the parameter types and Qt vtable references.\n\nQt expects fixed OS threads to be used for each QObject. When you first call `qapplication.New`, that will be considered the [Qt main thread](https://doc.qt.io/qt-6/thread-basics.html#gui-thread-and-worker-thread).\n\n- When accessing Qt objects from inside another thread, it's safest to use `Threading.Async()` (from this library) to access the Qt objects from Qt's main thread. The [Threading library](https://github.com/rcalixte/libqt6zig/tree/master/src/threading/libqt6zigthreading.zig) documents additional available strategies within the source code.\n\nQt C++ enums are projected as Zig enum structs of `i32` or `i64` values with the same names. For example, `Qt::AlignmentFlag` is projected as `enums.AlignmentFlag` within the `libqnamespace` module and exported by default as `qnamespace_enums.AlignmentFlag` though developers are free to use whatever naming convention they prefer for imports. Enums are currently defined as either `i32` or `i64` (where necessary) in the Zig API and as `i64` when expected as a parameter or returned as a type by the Zig API.\n\nSome C++ idioms that were difficult to project were omitted from the binding. This can be improved in the future.\n\n### Q4. What build modes are supported by the library?\n\nCurrently, only `ReleaseFast`, `ReleaseSafe`, and `ReleaseSmall` are supported. The `Debug` build mode is not supported. This may change in the future. The default build mode is `ReleaseFast`. To change the build mode:\n\n```bash\nzig build -Doptimize=ReleaseSafe\n```\n\n### Q5. Can I use Qt Designer and the Qt Resource system?\n\nMIQT (the upstream Qt bindings for Go) has a custom implementation of Qt `uic` and `rcc` tools, to allow using [Qt Designer](https://doc.qt.io/qt-6/qtdesigner-manual.html) for form design and resource management. There is work in progress to support Qt Designer with this library in the future.\n\n### Q6. How can I add bindings for another Qt library?\n\nFork this repository and add your library to the `genbindings/config-libraries` file. [Read more »](cmd/genbindings/README.md)\n\nSpecial Thanks\n--------------\n\n- [@mappu](https://github.com/mappu) for the [MIQT](https://github.com/mappu/miqt) bindings that provided the phenomenal foundation for this project\n\n- [@arnetheduck](https://github.com/arnetheduck) for proving the value of collaboration on the back-end of this project while working across different target languages\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frcalixte%2Flibqt6zig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frcalixte%2Flibqt6zig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frcalixte%2Flibqt6zig/lists"}