A few days ago I pinged Alberto Ruiz, a core GNOME contributor working at Red Hat, and brought up the idea of having a meeting between GNOME and Rust. It was becoming clear that more and more GNOME devs were starting to try Rust out. I asked if they'd like chat about Rust, some of GNOME's architecture, and how working with GNOME in Rust feels today.
Alberto pulled together a group of people on the GNOME side, and today we met with them for the first time. It was a relaxed meeting, getting to know each other and then diving into some of the trickier parts (from a language interop perspective) of GNOME. I think both sides came away feeling positive and looking forward to future meetings, with interest on both sides in working together and exploring what might be possible. There's also a deep belief in open source and working with community that was shared by all.
In brief, there are some challenges in using GObject from Rust due to GObject's dynamic nature. There is some precedence here, like the work on Neon. We need to do some more initial investigation. We also talked about doing an in-person dev sprint to help work through some of the technical issues at some point in the future. There's also interest in replacing the C in some of the lower-level components, like gstreamer, with Rust.
- Jonathan Turner (Rust)
- Niko Matsakis (Rust)
- Aaron Turon (Rust)
- Alberto Ruiz (GNOME)
- Zeeshan Ali (GNOME)
- Sebastian Dröge (GNOME)
- Christian Hergert (GNOME)
- Richard Hughes (GNOME)
- GObject overview (GType, GValue, classes, interfaces, properties, signals...)
- GObject Introspection overview (gtk-doc, clang, libtool) (source -> GIR -> typelib -> consume)
- Experience with Rust/GStreamer integration (Sebastian)
Overview of GObject system
- Used for basically everything in GNOME - all the way through the stack
- Copy/assign/destroy design
- Closure support via callbacks
- Implemented using big vtables
- Supports inheritance, hiding private data, public interfaces
- Emphasis on getters/setters etc
- More recently, GObject introspection. Takes compiled code together with introspection details in an annotation system. It lets higher-level languages call into GObject system. Obviates the need for a ton of separate language bindings.
- GObjects can implement multiple interfaces, including at runtime
- GTK widget in e.g. Gimp
- Might have hierarchy of 7 layers or so, with GObject at the bottom
Questions from Niko:
- "GObject is a runtime library?"
- It's built on top of glib, and provides the object layer on top
- "So you 'instantiate' the hierarchy at runtime?"
- "Is it determined by data I'm loading? or is it static?"
- Yes, it's done dynamically
- seems plausible to "map" this to Rust, the same way that you do via C. You could have API calls that register and invoke methods, etc
- IOW, it doesn't match directly to language concepts in Rust, but could be a dynamic system that you call into
- Rust offers a rich macro system that might help you eliminate boilerplate code for declaring classes/your setup. Could auto-generate from a declarative spec. Maybe you could even generate a more "Rust native" API on top
- What about using the introspection file to create a binding in Rust?
- Absolutely. You'd probably want to use the plugin system to generate code from the introspection files. (Plugins are not available on the stable channel today, but we have plans to work toward stabilization)
We don't want to force everyone into using Rust. So we want people to be able to subclass objects that are written in Rust.
- Today, using widgets through gtk-rs seems to work pretty well. But if I want to subclass/override, it's a lot harder.
- Where/how do you see using Rust to start?
- First, core librarties like GStreamer. Wanting to replace certain bits of their inner implementation details, while retaining the GObject interface to the rest of the world
- Second, want to build Rust bindings on top of existing libraries (but of course, you want to be able to layer more on top...)
- There's an effort right now to bridge Rust into V8 and other engines. Likely the lessons learned there will be quite relevant to GObject, even though it's not a VM per se. There are a lot of commonalities, since it's a dynamic object system.
- One place Vala has been successful is providing a better developer experience, while providing C ABI
- An example here is the Diesel project, which does something similar with compiler plugins and working with databases/SQL (http://diesel.rs)
- We've mentioned inheritance. Another issue is properties and signals
- In Vala, a signal is a prototype with the "signal" keyword in front of it. On the implementation side, it's a callback
- It's very similar to event in C#; a list of callbacks, possibly with return values and in/out params, including FFI marshalling (e.g. through libffi)
- Has notion of "accumulator" that allows you to interpret the return value from the callbacks on the way back, e.g. allowing you to stop invoking more callbacks
- Presumably there's a library that manages all of this at runtime?
- Yes, it's all part of the GObject type system, which also manages marshalling
- We should be able to just use that same runtime system, perhaps with annotations on the Rust side that hook things in automatically
Experience from GStreamer
- A little bit of C code that's doing all the GObject stuff. It calls directly into Rust code.
- The Rust code doesn't know anything about GObject, doesn't use inheritance, etc
- For GStreamer, we want to get rid of inheritance anyway; it's confusing for the users
- Benefiting not just from safety, but also from multithreading
- At the lowest level, we have buffers with an ownership story very similar to what Rust provides
- Would love to entirely rewrite in Rust
- We may want to do a more focused effort for the GObject.
- Low level stuff is an easy first win.
We need to explore further, but sounds like gtk-rs may be at a "get it done" level now and may need further work.
- Who would be a good set of people for the hackfest?
- What's the focus?
- Aaron: seems like the GObject integration seems to be the piece that needs the deep thinking between both sides
- Niko: some early exploration ahead of times seems good
- Alberto: we need to think about distribution of Rust code for the different distros
- Christian: we need good build system integration. eg) autotools
- Aaron: yes to both. We're already actively working on with distros and on build system integration
- Hackfest. Since getting progress on working with GObject from both directions may take work between both seasoned Rust and GNOME engineers, it seems like a hackfest to kick off the deeper work sounds like a good idea.
- Alberto: Put together a list of who should be involved
- Alberto: Work on where we should meet
- Alberto: Looking into possible sponsorship
- Aaron: help with the above from the Mozilla side
- What needs to happen before the hackfest?
- Alberto: do some initial push on dbus
- Niko: up for mini hackfest to kick things off
- We need a way of tracking the backlog of work, so we can track progress and pick things up if they drop off
- Christian: investigating integrating rustup with Builder
- brson (Brian Anderson) - would be a great contact
- Publicize the effort on all sides
- Jonathan: write the write-up from the meeting
- Jonathan and Alberto: set up next meeting time