Hacker News new | past | comments | ask | show | jobs | submit login
Rust Qt Binding Generator (github.com/kde)
206 points by vbsteven on May 18, 2018 | hide | past | favorite | 42 comments



I'm the author of the generator. There's a presentation on the project here: https://fosdem.org/2018/schedule/event/rust_qt_binding_gener...

Happy to answer questions.


Hi Jos, and thanks for coming up with this.

I found the project quite useful as a way to move away from C++ to Rust [0]. Of course, there were still some unsupported features, but that didn't stop me.

I did some additional work [1], where properties can be writeable references to Rust objects, and where I hope to make QML objects (list items) possible to create from Rust as the next step.

I'm sure you thought about those problems before, and I'm curious if you know any non-obvious solutions. Apart from that, what's the preferred way to submit changes?

[0] https://github.com/rhn/notquick/

[1] https://github.com/rhn/rust-qt-binding-generator


Your notquick [0], "a nice workflow for emails that works for me", is similar to a topic I've thought about a lot and which was one of the reasons to start RQBG. (I'd like to tie my mail more to my projects and tasks via content addressable storage and RDF). Coding in Rust is fantastic, but the GUI options are not there yet. Hence RQBG which is meant to stay small (<3k lines atm).

Your project uses it in the right way: just commit the generated files. It's a drag and error-prone to write so much binding code by hand.

> some additional work where properties can be writeable references to Rust objects

You can nest objects. The demo code does this. Here's an example where both Parent and Child are a QObject:

    "objects": {
        "Child": {
            "type": "Object",
            "properties": [
                "name": {
                    "type": "QString"
                }
            ]
        },
        "Parent": {
            "type": "Object",
            "properties": [
                "child": {
                    "type": "Child"
                }
            ]
        }
    }
> some additional work [...] where I hope to make QML objects (list items) possible to create from Rust

You'd like to use object types as itemProperties as well? That's not possible at the moment, but a logical extension.

Experimenting in your own branch is a good way to start. Wishes and designs for them can be discussed in the issue tracker: https://bugs.kde.org/describecomponents.cgi?product=rust-qt-...

Currently, generated model code derives from QObject (Object) or QAbstractItemModel (List and Tree). Deriving from QWidget or QQuickItem would make it possible to write GUI components in Rust as well. Those classes are large though and I've not yet had the urge/need to try that.


By writeable references, I meant replacing one QML reference by another:

    RustFoo {id: "foo"}
    RustBar {
      foo_field: foo
    }
This is possible with my branch. Your above example needs to be amended the following way:

    "child": {
        "type": "Child",
    +     "write": "true"
    }
The API changes quite a bit unfortunately, and is no longer so nice to use.

Unfortunately, my ideas to use (read-only) objects in itemProperties all end up complicating the API even worse, with abundant Box<>es and wrappers over wrappers. I can't find an elegant way to work around the mismatch between some Rust and C++ concepts (mostly lifetimes), but I expect to come up with something worth discussing within a couple of weeks.


> The API changes quite a bit unfortunately, and is no longer so nice to use.

The object property could be changed to use QSharedPointer<X> when it is writable instead of a raw pointer (const X*). The setter could be done completely in C++ initially, since the main use case, as you show, is to assign that value in QML or Qt code.

> objects in itemProperties [..] I expect to come up with something worth discussing within a couple of weeks

Looking forward to it!

For any Qt, QML or Rust experts reading this: I'd love your keen eyes on the generated code from Rust Qt Binding Generator.


Does it use native system dialogs for opening files etc.?


On Windows and macOS, by default Qt will use the native file dialog.


How difficult is it to hook up to OpenGL?


By default Qt renders with OpenGL. You can talk to OpenGL via the Qt APIs. You can provide application logic in Rust, but the actual GUI is still written en C++ or QML.

You can use Qt 3D for a UI with Rust logic. Writing a 3d scene with the declarative QML language is nice. Or you do this with your favorite text editor or Qt 3D Studio.

http://blog.qt.io/blog/category/qt-3d/


I guess I meant, how difficult is it to have a OpenGL component with relatively arbitrary OpenGL commands issued from Rust. I don't really care if the buttons are rendered in OpenGL or not, but I need an OpenGL pane inside a normal GUI. Imagine a Rust CAD application with a QT GUI.

QT-3D doesn't really fit my use case unfortunately.


RQBG does not generate bindings for that, but you could derive from QOpenGLWidget and write FFI to call into Rust for painting and resizing. Then you'd use Glium to do the painting. You can still use RQBG for the application logic.

http://doc.qt.io/qt-5/qopenglwidget.html#context

https://github.com/glium/glium


Word, thanks!


I am no developer but like to toy around, build small tools and automate stuff. So i often can't wrap my head around programming stuff promoted on HN (also i simply can't wrap my head around rust since i never really learned programming from the ground up...).

But stuff like this, some Binding Generator really amazes me and i am also able to understand the code. Had the same feeling when i was working on some REST API Binding in Elixir, and was looking at other Repos and found a generated Slack Package. Out-of-the-box solutions like this are great (myself would start to write every function by hand and probably stop half through and try something else...). Thank you for making something like this open source so beginners like myself can take a look :)


> (also i simply can't wrap my head around rust since i never really learned programming from the ground up...).

If you want to learn, alternate between studying and doing.

Read up on the basics, then go to doing mode, study something a bit more advanced, rinse and repeat.

Start the doing part by modifying existing code; perhaps some command line utility, they tend to be simple. Then add some features in it. You could also cut out all the functionality and implement something different in the skeleton.

It's a good idea to use version control even for your experiments, so you can go back when you inevitably break something so that it no longer compiles or works correctly. Sometimes breakage is obvious only much later. One thing is for sure -- you will break things, and version control will watch your back.

I'd recommend git (or hg), because they can be used locally without a server. Or a github account. (But really even zipping the directory is better than no history at all. But seriously, use proper version control tools.)

This method will work for Rust or anything else that can be similarly iterated.


Thank you for your tips.

Of course i am already using git. Working as a solo sysadmin i often automate stuff and need some scripts which i all version control. Since i like to work as a sysadmin i have of course also my own git server etc. :)

At the moment i try to focus on elixir, since i like the clean syntax and the REPL to try things (which is also a problem when i try to write something in rust. Since my programming workflow is pretty much based on try and error while i have the feeling a rust (or c) developer often knows beforehand what he puts into the function and what will come out). At work i often need to communicate with some kind of API (for example automatic sorting of pages in confluence) and all this GenServer Stuff helps me in Elixir.

But i think Rust would be a good choice if i need to write something more metal. Some small command line utility on one of the servers. Will try your "change an existing code"-approach!


Hey man, you ARE a developer! And if your atleast trying to understand hn stuff, you are on the road to becoming a good one. Never to late to go back to basics.


> (also i simply can't wrap my head around rust since i never really learned programming from the ground up...).

C is a good language for learning this. Just don't use your resulting programs on untrusted input; you _will_ make mistakes that _will_ result in security flaws.

Once you've shot yourself in the foot enough times (everybody does), you'll be able to come back to Rust and understand what it's doing. Many design choices in Rust won't make any sense until you've experienced the problems they solve.

For example, lifetimes in Rust make explicit what you would normally need to track implicitly in C.


Already took a look at C. But my problem is: Working with all these modern languages (Clojure, Go, Elixir, ...) i got really comfortable with all these nice toolchains and package managers. I also really like the Rust toolchain. So i tried my luck at rust more often as on C ;)


This, together with the Rust autogenerated bindings for GStreamer (https://github.com/sdroege/gstreamer-rs) make up for my two favourite work-related C / C++ technologies. Kudos for this, it's great to see how the Rust ecosystem is growing more and more every day!


I've seen a ton of bindings like this over the years, mostly implemented with SWIG (http://www.swig.org/)... for binding desktop GUI libraries like Qt, wxWidgets, etc to languages more accessible than C++.

It's all awesome, and this example here is certainly better than most (fantastic work!). The problem has traditionally been that most of these things are hobby projects from a single developer, and they go moribund when the developer gets bored and moves onto something else. Hell, if you Google around a bit, you might still find a "wxJava" binding on Sourceforge that I started and abandoned ~15 years ago.

To actually be fit for production use, one of these things needs to be either: (a) sponsored by some entity that keeps leadership continuity going, or (b) driven by an unusually large and unusually non-toxic volunteer group that is able to effectively mimic "a", or (c) created by someone who sees it as their crowning achievement and effectively dedicates their life to it. If this project really does have committed backing from the full KDE organization itself, then that's very encouraging!

I'd be interested to know if it's really an organization level commitment, or if they're just providing hosting for an experiment spearheaded by a single contributor (the Go team at Google has an "experimental" GUI library like this, but it's just one guy's noodling and no one really sees it as gaining traction outside of that). I'd also be curious what the cross-platform story is at this point (i.e. does it build and run on Windows?).

The only other examples I've seen so far that even come close to fitting the bill are in the Python community. And even that is a bit of a mess. There's confusion between two competing Qt bindings... and the wxWidgets binding has been going through a re-write for years, such that it's confusing whether to stay on the old version or adapt the new one (kinda like Python itself!).

But I still keep my eyes open, and look into this space every year or so. It would just be so awesome if there were a viable cross-platform desktop GUI solution, for a modern statically typed language somewhere between the extremes of C++ and JavaScript. I accept that desktop development is less important than it was 15 years ago... but I reject this notion that, "Desktop development is dead, just use Electron". There are still millions of use cases for true desktop applications. The only thing that's "dead" is the notion of being able to get away with just writing a native Windows version, and ignoring Macs (or vice-versa). And all of the cross-platform solutions have major problems, or are tied to languages or toolchains that people don't want to use, so that lack kinda sucks the oxygen out of the room for the open-source and hobbyist crowd on web forums.


> The problem has traditionally been that most of these things are hobby projects from a single developer, and they go moribund when the developer gets bored and moves onto something else.

I don't know for other libs, but Qt has strong API stability guarantees, so you need to generate the bindings only once per major Qt version - that is, once every five or six years. Just because the binding hasn't been commited to for a few years doesn't mean that it won't work.

> It would just be so awesome if there were a viable cross-platform desktop GUI solution, for a modern statically typed language somewhere between the extremes of C++

What's wrong, with, as you mentioned, C++ and Qt ? It can be as high-level as you want it to. I've been successfully developing a large desktop app with it and it has been a pleasure from start to end.


> It would just be so awesome if there were a viable cross-platform desktop GUI solution, for a modern statically typed language somewhere between the extremes of C++ and JavaScript.

For me that is JavaFX and Xamarin.Forms.

> The only thing that's "dead" is the notion of being able to get away with just writing a native Windows version, and ignoring Macs (or vice-versa)

Depending on the world region, you can still get away with targeting only Windows.

Not every country has lots of people able to pay for Apple devices, or even with Apple stores in every corner.


You are right, it would be great to see bindings as promising as these ones, but backed by some big players in the Qt world (such as e.g. KDAB which already provide very useful and well supported tools like the awesome GammaRay)


I completely agree with your thoughts. However, Rust is getting a lot of traction these days. Sooner or later more people will start to wonder "How do I write a portable app in it?" The Qt solution is a neat one, and might soon become the de facto standard - something similar happened with Python and Tk in the past.


I have dabbled a bit in Rust GUI programming for a small project and gtk-rs also works quite well. Is is also actively maintained and has regular releases.

http://gtk-rs.org/

Some people from the GNOME and Rust communities are working on macro magic that allows you to create GObject classes from Rust [1].

The downside is that the applications do not look native on macOS or Windows. But so doesn't Electron ;).

[1] https://gitlab.gnome.org/federico/gnome-class/


Historically, only languages with enormous amounts of traction have developed mature, consistently maintained GUI libraries. Right now, it's basically only C++, Python and Java that have any.


I have hope WebAssembly can make it happen. If you compile Qt and target WebAssembly, and compile Rust and target WebAssembly, it should all be able to work together automatically without needing tools like SWIG.


You can already compile Rust to x86 and Qt to x86, yet they don't work together automatically. Is there any reason to expect WebAssembly will be different?


I'm unfamiliar with WebAssembly, but I thought the spec was a little higher level. Two x86 apps might have the same op codes, but they don't always have the same calling conventions. How do you call a C function? You can't tell looking at the binary output, you only get the symbol name. Is it cdecl, stdcall, how many parameters and the names and types? Kotlin and Java work together, so do C# and F#.


ABI would still be a complication here, as different languages have different ways of calling into each other, different name mangling rules, etc.


> he only thing that's "dead" is the notion of being able to get away with just writing a native Windows version, and ignoring Macs (or vice-versa).

Linux and BSD however can safely be ignored. (Writing this from an Ubuntu laptop.)


If you're writing Qt, getting it to work on Linux if it already works on Windows probably isn't terrible. It certainly hasn't been for the PyQt GUI program I work on. Making a working Qt/X11 program work on Windows, on the other hand -- that could be painful.


Making a working Qt/X11 program work on Windows, on the other hand -- that could be painful.

I maintain a Qt application for Linux/macOS/Windows, with in total ~70kloc the last time I looked. It started as a Linux application, but porting to Windows was not a lot of effort and the amount of platform specific code is very small. The painful part on Windows are some non-Qt dependencies, such as libxml2, libxslt, DB XML, etc.

The port to macOS required much more platform-specific code to implement macOS-specific behavior (such as keeping the application running when the last window closes), building working, signed application bundles, etc.


(I was being sarcastic, by the way. That Linux isn't even mentioned in a sub-thread that talks about portability is disappointing.)


Must everything be so carefully screened for triggers? The GitHub project behind this overall thread mentions ONLY support for Linux/Docker, for crying out loud.


Well… it at least indicates that most people here don't use a free OS (even if we exclude Windows), and don't care much about free software. (Permissive licences however are loved, mostly because they allow proprietary derivative works.)

We used to talk about Windows/Linux for portability topics (conveniently ignoring BSD and others, I reckon). Somehow, Apple took over much of Linux's mindshare. And not just here. Many of my coworkers are asking for apple laptops. A huge fraction of keynote presenters use an apple laptop.

All that is a bit sad, considering Apple is even worse than Microsoft, freedom wise. They popularised the digital prison, that was originally confined mostly to game consoles. I'll never forgive that, no matter how much they contribute to open source.


I for one think software freedom is very important.


What are the safety guarantees of the resulting program?


The C++/Qt/QML code calls into Rust. The Rust parts are only calling to C++ with callbacks passed into Rust. Those callbacks are small and typical Qt. They do construction, destruction and (thread-safe) signaling.

So as per custom in Rust the safety rules of the C/C++ code is encoded in the Rust API which makes that part safe.

The C++ part calling Rust has the normal C++ safety guarantees, which are less strict than Rust. To have concurrency safety, it is recommended to only do the one GUI thread for C++ and do the multi-threading in Rust.


The safety guarantees are precisely those of a program which calls reams of legacy C++ cruft.


Would appreciate pointers to pure rust GUI libraries from any rust experts in this thread.


The current state of UI in rust is very early.

Most of the mature UI libs are bindings to another language.

However there are some native UI libs

https://github.com/PistonDevelopers/conrod/blob/master/READM...




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: