Quick overview of GObject
While C does not have objects or classes by itself, GObject makes it possible to write object-oriented C programs. The GObject library defines the GObject type system, which supports features like:
Classes and subclasses with single inheritance.
A class may implement multiple interfaces.
Virtual methods and static methods.
Signals, which are events emitted by objects (nothing to do with Unix signals). For example, a Button object may emit a "clicked" signal.
Properties, or getters/setters for values on objects, with notification of changes.
Introspection — asking the type system about which classes are registered and what features they contain.
Writing GObjects in C normally requires that you write an uncomfortable amount of boilerplate code to do things like register a new class, define its methods, register object signals and properties, etc. Due to the nature of C, many operations are not type-safe and depend on correct pointer casts, or on knowing the types that you should really be passing to varargs functions, which are not checked by the compiler.
Since GObject is a C library, it can be called from Rust through a
extern "C" functions. One could write
in Rust that match the layout that GObject functions expect: for
example, those structs could have fields with function pointers to
virtual method implementations.
Doing things that way is very verbose and cumbersome: it means using Rust as if it were C, and dealing with GObject's idiosyncrasies in a non-native language.
The fundamental goal of this Gnome-class crate is to let you write
GObject implementations in Rust with minimal or no boilerplate, and
with compile-time type safety all along. The goal is to require no
unsafe code on your part.
How is gnome-class different from glib-rs?
However, glib-rs is a language binding to GObject-based libraries. It lets you use GObject libraries from Rust; it does not let you implement new such libraries easily. That is the purpose of gnome-class: we generate GObject-compatible code, from Rust, and that has the same kind of Rust API as a "traditional" library would have if wrapped with glib-rs.
Goals of gnome-class
Let users write new GObject classes completely in Rust, with no unsafe code, and no boilerplate.
Generate GObject implementations that look exactly like C GObjects from the outside. The generated GObjects should be callable from C or other languages in exactly the same way as traditional GTK+/GNOME libraries.
Automatically emit GObject Introspection information so that the generated objects can be consumed by language bindings.
In the end, we aim to make it compelling for users to not write new GObject libraries in C, but rather to give them an "obvious" way to it in Rust. This should ensure higher-quality, safer code for GNOME's general-purpose libraries, while maintaining backwards compatibility with all the GObject-based infrastructure we have.
About this document
This is an overview of how gnome-class works. It is implemented as a
Rust procedural macro that extends the Rust language with
GObject-friendly constructs: for example, Rust does not have
signal keywords, but gnome-class adds them to the
It will be helpful for you to know a bit of how GObject works. Read the GObject Tutorial in the GObject Reference Guide. You can also read the source code for libraries which implement GObjects, for example, GTK+.
Please read this overview of how GObject Introspection works. This will give you a good idea of what we want to generate at some point with gnome-class.
While it will be helpful to have some basic understanding of compilers (parsers, analyzers, code generators), this is not necessary. This document will explain what you need to know for gnome-class's internals.
If you find any issues with this document, like missing information, unclear explanations, or anything at all, please file an issue in the gnome-class issue tracker, or even submit a merge request with a correction!