But this session is about different ones
Lines of code with cloc, 6.8M in total, 3rdparty excluded. Highlighted: languages from the watch list or the Qt Bridges candidates.
Skipped: HTML, XML, Markdown, CSS, Text, JSON, SVG, YAML, TOML, XSLT, XSD, diff, INI, CSV, Qt Linguist, XML (Qt/GTK), Qt Project, Mustache, ProGuard, Protocol Buffers, DTD, PO File, JSON5, PlantUML, IDL, Properties, Windows Resource File, Windows Module Definition, ANTLR Grammar, lex, reStructuredText
Three from outside Qt, three from inside.
pip install and never notice the languageLesson: adoption wins when the new language is invisible at the boundary, and a framework that talks to one language is great.
The quietest way a language enters an ecosystem is through the build.
$ pip install flake8 isort pyupgrade ...
$ flake8 . # seconds
$ pip install ruff
$ ruff check . # milliseconds
Qt ships a whole family of exactly this kind of tool.
| Tool | Job | Why it is a candidate | Difficulty |
|---|---|---|---|
rcc | Compiles resources into C++ | Files in, source out; no Qt types needed | low |
lrelease, lupdate | Translations | Parsing and file formats | low to medium |
qmlformat, qmllint | QML style and checks | Needs a QML parser (exists as a separate component) | medium |
windeployqt, macdeployqt | Packaging | Mostly file and process work | low |
uic | Forms to C++ | XML in, source out | medium |
qdoc | Documentation generator | Source comments in, HTML out (Clang to parse C++) | medium to high |
moc | The meta-object compiler | The big one: it must understand C++ | high |
for f in $(find . -name '*.qrc'); do
rcc "$f" -o /tmp/cpp.cpp
rcc-rs "$f" -o /tmp/rs.cpp
cmp /tmp/cpp.cpp /tmp/rs.cpp || echo "DIFF $f"
done
cargo and crates need a supply chain policy| Door | What the language gets | Who pays the maintenance | Example |
|---|---|---|---|
| 1. Binding | Qt's C++ API, mirrored | The binding team, forever | PySide, QtJambi |
| 2. Bridge | Logic in the language, UI in QML | A small meta-object boundary | Qt Bridges, CXX-Qt |
| 3. Interop | Call through the language's own FFI | The language community | Swift C++ interop, Zig @cImport |
| 4. Toolchain | A seat in Qt's build and CI | Qt's own infrastructure | Rust for QtWebEngine |
| 5. Protocol | Talks to a Qt UI over IPC, no FFI needed | Nobody, mostly | D-Bus, Qt Remote Objects |
Both need someone paid or devoted to keep them alive.
// Zig: headers become declarations
const c = @cImport({
@cInclude("qt_shim.h");
});
pub fn main() void {
const app = c.qapp_new();
defer c.qapp_free(app);
_ = c.qapp_exec(app);
}
Illustrative: qt_shim.h is a hypothetical C shim, see the next slides.
A tiny, officially stable C surface for registering types, properties, signals and slots with the QML engine would be a force multiplier.
/* qt_shim.h: hypothetical, illustrative only */
typedef struct QtApp QtApp;
typedef struct QtType QtType;
QtApp *qtapp_new(int argc, char **argv);
int qtapp_exec(QtApp *);
QtType *qttype_begin(const char *qml_name);
void qttype_property(QtType *, const char *name,
int meta_type,
QtGetter, QtSetter,
const char *notify);
void qttype_slot(QtType *, const char *name,
QtSlot fn);
int qttype_register(QtApp *, QtType *,
const char *uri,
int major, int minor);
comptime or an Odin hand-binding all target the same thingProtocol is underrated: great for Elixir, Gleam and Go back ends, where the runtime is the point.
C++26 reflection and the meta-object boundary
^^T, std::meta, annotations [[= ...]]-std=c++26 -freflectionQt supports all three compilers, so moc cannot go away soon. The question is the direction.
Q_GADGET: member names become rolessignals: and slots: blocks
// from the QRangeModel post
static consteval auto count()
{
constexpr auto ctx =
std::meta::access_context::current();
return nonstatic_data_members_of(
^^T, ctx).size();
}
QMetaObject from reflection, no moc runQML_ELEMENT, Q_GADGET, BINDABLE; GCC onlyExperimental, third party: github.com/wrocpp/reflect-moc
class Counter : public QObject {
RQT_OBJECT
RQT_PROPERTY(int value READ value
WRITE setValue
NOTIFY valueChanged)
public:
int value() const { return value_; }
[[= rqt::slot]] void setValue(int v) {
if (v == value_) return;
value_ = v;
emit valueChanged(v);
}
[[= rqt::names("value")]]
rqt::signal<void(int)> valueChanged;
private:
int value_ = 0;
};
QMetaObject table, so how it is made matters, not only C++QML_ELEMENT and qmltyperegistrar sit on top of moc output todayReflection is C++ arriving where Rust, Swift and Zig already are: describe the type, let the compiler do the rest.
…and a long tail: Go, Nim, Crystal, D, Dart, Roc, Hylo, cppfront
import QtWidgets, import QtQuick… for every installed Qt 6 module
import QtWidgets
@main
struct HelloWidgets: QtApplication {
init() {
let title: QString = "Hello, Qt!"
let widget = QWidget()
widget.setWindowTitle(title)
widget.resize(400, 300)
widget.show()
}
}
Adapted from Examples/HelloWidgets.
QString to String) are usable like Swift onesunsafeBitCastThe missing half is a bridge: Swift types exposed to QML. Annotations in the headers and the reflection work both help here. It is the natural next phase.
zig cc and zig c++: a drop-in cross compiler for C and C++@cImport
const std = @import("std");
pub fn main() void {
std.debug.print("Hello!\n", .{});
}
comptime can generate the QML registration from a struct: bridge-like ergonomics with no macro systemzig c++ as a CI cross compiler for Qt itself (an experiment worth running)moc-like step, so the meta-object has to be built by handVerdict: a community project if we provide the C surface.
import gleam/io
pub fn main() {
io.println("Hello, Qt!")
}
Verdict: protocol first (Gleam back end, QML front end). A bridge is the wrong shape here.
Qt is exactly the kind of codebase Carbon's story is written for:
huge, templated, macro-heavy, moc-processed C++.
package Sample api;
class Counter {
var value: i32;
fn Add[addr self: Self*](n: i32) {
self->value += n;
}
}
fn Main() -> i32 {
var c: Counter = {.value = 0};
c.Add(42);
return c.value;
}
import Cpp of existing headersQObject, templates and Q_OBJECT macrosApproximate: Carbon's syntax is still changing.
Verdict: watch, do not bet, and the same for cppfront. Keep Qt headers clean, and tell the Carbon team how Q_OBJECT breaks things.
Mojo can import Python modules, so PySide is reachable in principle today.
struct Point:
var x: Float64
var y: Float64
def __init__(out self, x: Float64, y: Float64):
self.x = x
self.y = y
def scale(mut self, k: Float64):
self.x *= k
self.y *= k
def main():
var p = Point(1.5, 2.0)
p.scale(2.0)
print(p.x, p.y)
Looks like Python, but struct, var and out/mut argument conventions are not valid Python: this is compiled, statically typed code.
from python import Python
def main():
var qt = Python.import_module(
"PySide6.QtCore")
print(qt.__version__)
Mojo's documented way to use Python modules. I have not tried this with PySide6.
arith, gpu, spirv…)Qt’s QML and shader pipelines offer precedents for staged compilation, but cross-language bindings still need explicit integration.
func.func @add(%a: i32,
%b: i32) -> i32 {
%0 = arith.addi %a, %b : i32
func.return %0 : i32
}
The dialect is part of each operation name.
define i32 @add(i32 %a, i32 %b) {
entry:
%0 = add i32 %a, %b
ret i32 %0
}
One fixed, low-level IR. MLIR lowers to it.
function %add(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = iadd v0, v1
return v2
}
Its own small IR, straight to machine code. No LLVM.
For one add they look alike: the difference shows up with tensors, GPUs and compile time, not with integers.
Three C-shaped languages, three different bets
fn C.name, no binding generator
#flag -lm
#include <math.h>
fn C.sqrt(x f64) f64
fn main() {
name := 'Qt'
println('Hello, ${name}!')
println(C.sqrt(2.0))
}
Verdict: nothing to do except publish the C surface and let anyone try.
foreign import links a C library but cannot parse headers; a vendor collection ships SDL, raylib, Vulkan…
package main
foreign import qtshim "system:qtshim"
@(default_calling_convention = "c")
foreign qtshim {
qtapp_new :: proc(argc: i32,
argv: [^]cstring) -> rawptr ---
qtapp_exec :: proc(app: rawptr) -> i32 ---
}
main :: proc() {
app := qtapp_new(0, nil)
_ = qtapp_exec(app)
}
Illustrative: qtshim is the hypothetical C surface.
Verdict: friendly tier. With the C surface, an Odin vendor:qt is a weekend of someone else's work.
extern fn
// calling C
extern fn hypot(x: f64, y: f64) -> f64;
// a generic function
fn twice(x) { x + x }
// a growable array of structs
var items: Item[>..] = [];
Snippets from the project page.
Verdict: watch. Emitting C means the C surface is the whole interop story.
| Language | Why it comes up | Qt angle |
|---|---|---|
| Go | Cloud, CLI tools, huge hiring pool | Community bindings exist (e.g. miqt); cgo cost and GC/event-loop mismatch |
| Nim | Python-like, compiles to C or C++ | Compiling to C++ is a real interop advantage |
| D | Long history with C++ interop | dqt is the cautionary tale |
| Dart | Flutter is a direct neighbour | Competitor and potential consumer of our back end |
| Hylo, Roc, Vale | New ideas on safety and value semantics | Too early; only worth following |
| Language | C / C++ interop | Metadata for QML | Stability | Qt story today |
|---|---|---|---|---|
| Python | Shiboken | generators | stable | Qt for Python, Bridges |
| Rust | CXX | proc macros | stable | Bridges, CXX-Qt |
| C# | C via P/Invoke | attributes, generators | stable | Bridges |
| Swift | official C++ interop | macros, attributes | stable | annotations, Bridges |
| Kotlin / Java | JNI | annotations | stable | QtJambi, Bridges |
| Go | C via cgo | tags, go generate | stable | community bindings |
| Zig | C only | comptime | pre-1.0 | libqt6zig |
| Gleam | NIFs and ports | no macros | young 1.x | none |
| Carbon | the whole point, not ready | unknown | experimental | none |
| Mojo | C and Python | limited | 1.0 (Aug 2026) | via Python |
| V | C, trivially | weak | pre-1.0 | none |
| Odin | C only | no reflection | stable, no 1.0 | none |
| Goose | C via extern fn | unknown | experimental | none |
green good fit - orange workable - red gap
"Cheap" things first
metatypes.json and qmltypes as inputs for generators| Tier | What Qt commits to | Candidates |
|---|---|---|
| Official | Maintained and released with Qt | C++, QML, Python, Bridges: Rust and C#; Qt's own tools could join here |
| Supported surface | Annotations and docs, no bridge yet | Swift (qt-swift is the natural base) |
| Friendly | Stable C surface, metadata, conformance suite | Zig, Odin, Go, Nim, V: anything with a C FFI |
| Watch | Nothing, except attention, and perhaps opinion? | Carbon, Mojo, Gleam, Goose, Hylo… |
The top tier is expensive on purpose. The lower tiers let communities do the expensive part.
Some died from the maintenance tail: a new language needs an owner outside Qt before it needs a place inside it.
Cristián Maureira-Fredes
@cmaureir
Qt Contributors' Summit 2026 | @cmaureir