-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PoC: qt using auto-generated bindings #17270
base: master
Are you sure you want to change the base?
Conversation
This PR uses status-desktop as a "big enough" playground to experiment with a new set of bindings for Qt that are automatically generated from the Qt source code (similar to how PySide and other "modern" Qt bindings are done) - these bindings would serve as a more solid starting point for future qt/qml-based applications in Nim (and potentially other languages near and dear to us). The bindings themselves first expose Qt to C and then C to Nim - although Nim is used here, the C bindings can also be construed as a stand-alone exposition of Qt that can be imported to other languages than Nim, using `C` FFI as the lingua franca (which is a lot easier to work with than C++). This PoC is here mainly to show the feasibility of the approach and as such does not make any actual changes to the desktop code - instead, compatibilty is kept via a "DOtherSide" emulation layer implemented entirely in Nim using the automatically generated bindings - the PoC also doesn't touch the various status-specific extensions and hacks to DOtherSide which probably deserve another home (StatusQ?) - that said, most of these status-fork-specifc extensions could now be removed because they are available natively from the automatic bindings (QSettings, signal connections etc). Obviously, to benefit fully from the bindings, one would have to do work on the DSL itself as well which would drastically reduce the amount of boilerplate needed to interact with qt (in declaring properties, signals etc) - a trivial example is a property definition with slots and change signals that could be reduced to: ``` QtObject: type MyObject = ... name {.property.}: string ``` QObject instances would of course no longer have to be wrapped in QVariant etc. The compatibiltiy layer would allow any nimqml-based application to transition gradually / doesn't require any up-front porting effort. As-is, the PoC already demonstrates a few things: * build system simplification - the new bindings don't require `DOtherSide` to be built and linked separately (the build system is kept for the status extensions, not the DOtherSide code itself) - instead, the bindings are built as part of the Nim application (sourcing Qt installation information from `pkg-config`) simplifying cross-compilation (ie building on android) and zero-to-hero story for using Qt in Nim. The same technique could trivially be applied to `StatusQ` and `DOtherSide` as well. * ABI-compatible generation of QMetaObject data at compile time - the current nimqml bindings use a hybrid of dynamic metadata and dotherside-based C++ code which has a number of downsides, the most obvious being the difficulty to expose QObject-based properties from Nim to QML - the DOtherSide bindings also cannot fully interact with threaded signals, Qt-registered instantiation/copying, Qml registration etc. With full access to the Qt API and full integration with QMetaObject, this becomes not only feasible but also future-proof (relying on the API/ABI stability guarantees of Qt itself) * support for all inheritance-based Qt types (todo: multiple inheritance) - in the automatically generated bindings, virtual functions are available for overriding, static dispatch to base class implementations are exposed etc * signals and slots can be connected using type-safe lambda expressions (instead of string-based connect methods) - this support can also be extended to QObject-derived types in Nim - across language borders (C++/QML/Js), string-based conncetions continue to be supported. * full access to most/all QVariant types * efficient / small binaries - only the parts of qt that are actually used in the application result in binding code being generated/compiled/linked (unlike dotherside etc which build/link an entire set of bindings) - for QMetaObject, this binding code is almost exactly the same as `moc` would generate (this is how the ABI compatibiltiy "happens"), without a separate `moc` program (nim macros / compile-time introspection ftw). The binding approach serves as a complement to anything developed natively in C++ for Qt, ie this approach extends rather than replaces the ability to use native code - the generator that creates the bindings can similarly be used with hand-written C++ code that follows Qt conventions (not part of the poc though) - just like `shiboken` can be used to generate PySide extensions. Tested this on linux mainly for now - likely some small adjustments are needed for other platforms.
Jenkins BuildsClick to see older builds (28)
|
On a side note, Qt does not allow using the same class name for different QObject-derived instances because property registrations are done using the class name as lookup key - the new integration with qmetaobject causes some problems in status desktop because there are a lot of qobjects named |
Note to self: linux fails to compile due to the usage of |
This PR uses status-desktop as a "big enough" playground to experiment with a new set of bindings for Qt that are automatically generated from the Qt source code (similar to how PySide and other "modern" Qt bindings are done) - these bindings would serve as a more solid starting point for future qt/qml-based applications in Nim (and potentially other languages near and dear to us).
The bindings themselves first expose Qt to C and then C to Nim - although Nim is used here, the C bindings can also be construed as a stand-alone exposition of Qt that can be imported to other languages than Nim, using
C
FFI as the lingua franca (which is a lot easier to work with than C++, in binding code).This PoC is here mainly to show the feasibility of the approach and as such does not make any actual changes to the desktop code - instead, compatibilty is kept via a "DOtherSide" emulation layer implemented entirely in Nim using the automatically generated bindings - the PoC also doesn't touch the various status-specific extensions and hacks to DOtherSide which probably deserve another home (StatusQ?) - that said, most of these status-fork-specifc extensions could now be removed because they are available natively from the automatic bindings (QSettings, signal connections etc).
Obviously, to benefit fully from the bindings, one would have to do work on the DSL itself as well which would drastically reduce the amount of boilerplate needed to interact with qt (in declaring properties, signals etc) - a trivial example is a property definition with slots and change signals that could be reduced to:
QObject instances would of course no longer have to be wrapped in QVariant etc.
The compatibiltiy layer would allow any nimqml-based application to transition gradually / doesn't require any up-front porting effort.
As-is, the PoC already demonstrates a few things:
DOtherSide
to be built and linked separately (the build system is kept for the status extensions, not the DOtherSide code itself) - instead, the bindings are built as part of the Nim application (sourcing Qt installation information frompkg-config
) simplifying cross-compilation (ie building on android) and zero-to-hero story for using Qt in Nim. The same technique could trivially be applied toStatusQ
andDOtherSide
as well.moc
would generate (this is how the ABI compatibiltiy "happens"), without a separatemoc
program (nim macros / compile-time introspection ftw).The binding approach serves as a complement to anything developed natively in C++ for Qt, ie this approach extends rather than replaces the ability to use native code - the generator that creates the bindings can similarly be used with hand-written C++ code that follows Qt conventions (not part of the poc though) - just like
shiboken
can be used to generate PySide extensions.Tested this on linux mainly for now - likely some small adjustments are needed for other platforms.
What does the PR do
Affected areas
Architecture compliance
My PR is consistent with this document: Status Desktop Architecture Guide
Screenshot of functionality (including design for comparison)