{"id":444,"date":"2017-09-06T15:47:36","date_gmt":"2017-09-06T13:47:36","guid":{"rendered":"https:\/\/coaxion.net\/blog\/?p=444"},"modified":"2017-09-09T11:17:52","modified_gmt":"2017-09-09T09:17:52","slug":"exporting-a-gobject-c-api-from-rust-code-and-using-it-from-c-python-javascript-and-others","status":"publish","type":"post","link":"https:\/\/coaxion.net\/blog\/2017\/09\/exporting-a-gobject-c-api-from-rust-code-and-using-it-from-c-python-javascript-and-others\/","title":{"rendered":"Exporting a GObject C API from Rust code and using it from C, Python, JavaScript and others"},"content":{"rendered":"<p>During the last days I was experimenting a bit with implementing a <a href=\"https:\/\/en.wikipedia.org\/wiki\/GObject\" target=\"_blank\">GObject<\/a> C API in <a href=\"https:\/\/www.rust-lang.org\" target=\"_blank\">Rust<\/a>. The results can be found in <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\" target=\"_blank\">this repository<\/a>, and this is something like an overview of the work, code walkthrough and status report. Note that this is quite long, a little bit further down you can find a table of contents and then jump to the area you&#8217;re interested in. Or read it chapter by chapter.<\/p>\n<p>GObject is a C library that allows to write object-oriented, cross-platform APIs in C (which does not have support for that built-in), and provides a very expressive runtime type system with many features known from languages like Java, C# or C++. It is also used by various C library, most notably the cross-platform <a href=\"https:\/\/www.gtk.org\" target=\"_blank\">GTK UI toolkit<\/a> and the <a href=\"https:\/\/gstreamer.freedesktop.org\" target=\"_blank\">GStreamer multimedia framework<\/a>. GObject also comes with strong conventions about how an API is supposed to look and behave, which makes it relatively easy to learn new GObject based APIs as compared to generic C libraries that could do anything unexpected.<\/p>\n<p>I&#8217;m not going to give a full overview about how GObject works internally and how it is used. If you&#8217;re not familiar with that it might be useful to first read the <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/\" target=\"_blank\">documentation<\/a> and especially the <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/pt02.html\" target=\"_blank\">tutorial<\/a>. Also some C &#038; Rust (especially unsafe Rust and FFI) knowledge would be good to have for what follows.<\/p>\n<p>If you look at the code, you will notice that there is a lot of unsafe code, boilerplate and glue code. And especially code duplication. I don&#8217;t expect anyone to manually write all this code, and the final goal of all this is to have Rust macros to make the life easier. Simple Rust macros that make it as easy as in C are almost trivial to write, but what we really want here is to be able to write it all only in safe Rust in code that looks a bit like C# or Java. There is a <a href=\"https:\/\/github.com\/nikomatsakis\/gnome-class\" target=\"_blank\">prototype<\/a> for that already written by Niko Matsakis, and a <a href=\"http:\/\/smallcultfollowing.com\/babysteps\/blog\/2017\/05\/02\/gnome-class-integrating-rust-and-the-gnome-object-system\/\" target=\"_blank\">blog post<\/a> with further details about it. The goal for this code is to work as a manual example that can be integrated one step at a time into the macro based solution. Code written with that macro should in the end look similar to the following<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"gnome-class example\">gobject_gen! {\r\n    class Counter {\r\n        struct CounterPrivate {\r\n            f: Cell&lt;u32&gt;\r\n        }\r\n\r\n        fn add(&amp;self, x: u32) -&gt; u32 {\r\n            let private = self.private();\r\n            let v = private.f.get() + x;\r\n            private.f.set(v);\r\n            v\r\n        }\r\n\r\n        fn get(&amp;self) -&gt; u32 {\r\n            self.private().f.get()\r\n        }\r\n    }\r\n}<\/pre>\n<p>and be usable like<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">let c = Counter::new();\r\nc.add(2);\r\nc.add(20);<\/pre>\n<p>The code in my repository is already integrated well into <a href=\"http:\/\/gtk-rs.org\" target=\"_blank\">GTK-rs<\/a>, but the macro generated code should also be integrated well into GTK-rs and work the same as other GTK-rs code from Rust. In addition the generated code should of course make use of all the type FFI conversion infrastructure that already exists in there and was explained by Federico in his blog post (<a href=\"https:\/\/people.gnome.org\/~federico\/blog\/how-glib-rs-works-part-1.html\" target=\"_blank\">part 1<\/a>, <a href=\"https:\/\/people.gnome.org\/~federico\/blog\/how-glib-rs-works-part-2.html\" target=\"_blank\">part 2<\/a>).<br \/>\nIn the end, I would like to see such a macro solution integrated directly into the GLib bindings.<\/p>\n<h3 id=\"toc\">Table of Contents<\/h3>\n<ol>\n<li><a href=\"#why\">Why?<\/a><\/li>\n<li><a href=\"#boxed\">Simple (boxed) types<\/a><\/li>\n<li><a href=\"#objects\">Object types<\/a>\n<ol>\n<li><a href=\"#inheritance\">Inheritance<\/a><\/li>\n<li><a href=\"#vfuncs\">Virtual Methods<\/a><\/li>\n<li><a href=\"#properties\">Properties<\/a><\/li>\n<li><a href=\"#signals\">Signals<\/a><\/li>\n<\/ol>\n<li><a href=\"#interfaces\">Interfaces<\/a><\/li>\n<li><a href=\"#c\">Usage from C<\/a><\/li>\n<li><a href=\"#rust\">Usage from Rust<\/a><\/li>\n<li><a href=\"#python-js\">Usage from Python, JavaScript and Others<\/a><\/li>\n<li><a href=\"#what-next\">What next?<\/a><\/li>\n<\/ol>\n<h3 id=\"why\">Why?<\/h3>\n<p>Now one might ask why? GObject is yet another C library and Rust can export plain C API without any other dependencies just fine. While that is true, C is not very expressive at all and there are no conventions about how C APIs should look like and behave, so everybody does their own stuff. With GObject you would get all kinds of object-oriented programming features and strong conventions about API design. And you actually get a couple of features (inheritance, properties\/signals, full runtime type system) that Rust does not have. And as bonus points, you get bindings for various other languages (Python, JavaScript, C++, C#, &#8230;) for free. More on the last point later.<\/p>\n<p>Another reason why you might want to do this, is to be able to interact with existing C libraries that use GObject. For example if you want to create a subclass of some GTK widget to give it your own custom behaviour or modify its appearance, or even writing a completely new GTK widget that should be placed together with other widgets in your UI, or for implementing a new GStreamer element that implements some fancy filter or codec or \u2026 that you want to use.<\/p>\n<h3 id=\"boxed\">Simple (boxed) types<\/h3>\n<p>Let&#8217;s start with the simple and boring case, which already introduces various GObject concepts. Let&#8217;s assume you already have some simple Rust type that you want to expose a C API for, and it should be GObject-style to get all the above advantages. For that, GObject has the concept of <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/gobject-Boxed-Types.html\" target=\"_blank\">boxed types<\/a>. These have to come with a &#8220;copy&#8221; and &#8220;free&#8221; function, which can do an actual copy of the object or just implement <a href=\"https:\/\/en.wikipedia.org\/wiki\/Reference_counting\" target=\"_blank\">reference counting<\/a>, and GObject allows to register these together with a string name for the type and then gives back a type ID (<em>GType<\/em>) that allows referencing this type.<\/p>\n<p>Boxed types can then be automatically used, together with any C API they provide, from C and any other languages for which GObject support exists (i.e. basically all). It allows to use instances of these boxed types to be used in signals and properties (see further below), allows them to be stored in <em>GValue<\/em> (a container type that allows to store an instance of any other type together with its type ID), etc.<\/p>\n<p>So how does all this work? In my repository I&#8217;m implementing a boxed type around a <em>Option<String><\/em>, one time as a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/tree\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\" target=\"_blank\">&#8220;copy&#8221; type<\/a> <em>RString<\/em>, another time <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/tree\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/shared_rstring\" target=\"_blank\">reference counted<\/a> (<em>SharedRString<\/em>). Outside Rust, both are just passed as pointers and the implementation of them is private\/opaque. As such, it is possible to use any kind of Rust struct or enum and e.g. marking them as <em>#[repr(C)]<\/em> is not needed. It is also possible to use <em>#[repr(C)]<\/em> structs though, in which case the memory layout could be public and any struct fields could be available from C and other languages.<\/p>\n<h4>RString<\/h4>\n<p>The actual implementation of the type is in the <em>imp.rs<\/em> file, i.e. in the <em>imp<\/em> <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\/imp.rs#L14-L29\" target=\"_blank\">module<\/a>. I&#8217;ll cover the other files in there at a later time, but <em>mod.rs<\/em> is providing a public Rust API around all this that integrates with GTK-rs.<\/p>\n<p>The following is the whole implementation, in safe Rust:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[derive(Clone)]\r\npub struct RString(Option&lt;String&gt;);\r\n\r\nimpl RString {\r\n    fn new(s: Option&lt;String&gt;) -&gt; RString {\r\n        RString(s)\r\n    }\r\n\r\n    fn get(&amp;self) -&gt; Option&lt;String&gt; {\r\n        self.0.clone()\r\n    }\r\n\r\n    fn set(&amp;mut self, s: Option&lt;String&gt;) {\r\n        self.0 = s;\r\n    }\r\n}<\/pre>\n<h5>Type Registration<\/h5>\n<p>Once the macro based solution is complete, this would be more or less all that would be required to also make this available to C via GObject, and any other languages. But we&#8217;re not there yet, and the goal here is to do it all manually. So first of all, we need to register this type somehow to GObject, for which (by convention) a C function called <em>ex_rstring_get_type()<\/em> should be defined which registers the type on the first call to get the type ID, and on further calls just returns that type ID. If you&#8217;re wondering what <em>ex<\/em> is: this is the &#8220;namespace&#8221; (C has no built-in support for namespaces) of the whole library, short for &#8220;example&#8221;. The <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\/imp.rs#L75-L94\" target=\"_blank\"><em>get_type()<\/em> function<\/a> looks like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_rstring_get_type() -&gt; glib_ffi::GType {\r\n    callback_guard!();\r\n\r\n    static mut TYPE: glib_ffi::GType = gobject_ffi::G_TYPE_INVALID;\r\n    static ONCE: Once = ONCE_INIT;\r\n\r\n    ONCE.call_once(|| {\r\n        let type_name = CString::new(&quot;ExRString&quot;).unwrap();\r\n\r\n        TYPE = gobject_ffi::g_boxed_type_register_static(\r\n            type_name.as_ptr(),\r\n            Some(mem::transmute(ex_rstring_copy as *const c_void)),\r\n            Some(mem::transmute(ex_rstring_free as *const c_void)),\r\n        );\r\n\r\n    });\r\n\r\n    TYPE\r\n}<\/pre>\n<p>This is all unsafe Rust and calling directly into the GObject C library. We use <a href=\"https:\/\/doc.rust-lang.org\/stable\/std\/sync\/struct.Once.html\" target=\"_blank\">std::sync::Once<\/a> for the one-time registration of the type, and store the result in a <em>static mut<\/em> called <em>TYPE<\/em> (super unsafe, but OK here as we only ever write to it once). For registration we call <em>g_boxed_type_register_static()<\/em> from GObject (provided to Rust via the <em>gobject-sys<\/em> crate) and provide the name (via <a href=\"https:\/\/doc.rust-lang.org\/stable\/std\/ffi\/struct.CString.html\" target=\"_blank\">std::ffi::CString<\/a> for C interoperability) and the copy and free functions. Unfortunately we have to cast them to a generic pointer, and then transmute them to a different function pointer type as the arguments and return value pointers that GObject wants there are plain <em>void *<\/em> pointers but in our code we would at least like to use <em>RString *<\/em>. And that&#8217;s all that there is to the registration. We mark the whole function as <em>extern &#8220;C&#8221;<\/em> to use the C calling conventions, and use <em>#[no_mangle]<\/em> so that the function is exported with exactly that symbol name (otherwise Rust is doing symbol name mangling), and last we make sure that no panic unwinding happens from this Rust code back to the C code via the <em>callback_guard!()<\/em> macro from the <em>glib<\/em> crate.<\/p>\n<h5>Memory Managment Functions<\/h5>\n<p>Now let&#8217;s take a look at the actual <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\/imp.rs#L42-L49\" target=\"_blank\">copy<\/a> and <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\/imp.rs#L51-L56\" target=\"_blank\">free<\/a> functions, and the actual constructor function called <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\/imp.rs#L34-L40\" target=\"_blank\"><em>ex_rstring_new()<\/em><\/a>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_rstring_new(s: *const c_char) -&gt; *mut RString {\r\n    callback_guard!();\r\n\r\n    let s = Box::new(RString::new(from_glib_none(s)));\r\n    Box::into_raw(s)\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_rstring_copy(rstring: *const RString) -&gt; *mut RString {\r\n    callback_guard!();\r\n\r\n    let rstring = &amp;*rstring;\r\n    let s = Box::new(rstring.clone());\r\n    Box::into_raw(s)\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_rstring_free(rstring: *mut RString) {\r\n    callback_guard!();\r\n\r\n    let _ = Box::from_raw(rstring);\r\n}<\/pre>\n<p>These are also unsafe Rust functions that work with raw pointers and C types, but fortunately not too much is happening here.<\/p>\n<p>In the constructor function we get a C string (<em>char *<\/em>) passed as argument, convert this to a Rust string (actually <em>Option<String><\/em> as this can be NULL) via <em>from_glib_none()<\/em> from the <em>glib<\/em> crate and then pass that to the Rust constructor of our type. <em>from_glib_none()<\/em> means that we don&#8217;t take ownership of the C string passed to us, the other variant would be <em>from_glib_full()<\/em> in which case we would take ownership. We then pack up the result in a Rust <em>Box<\/em> to place the new RString in heap allocated memory (otherwise it would be stack allocated), and use Box&#8217;s <em>into_raw()<\/em> function to get a raw pointer to the memory and not have its <em>Drop<\/em> implementation called anymore. This is then returned to the caller.<\/p>\n<p>Similarly in the copy and free functions we just do some juggling with Boxes: copy take a raw pointer to our RString, calls the compiler generated <em>clone()<\/em> function to copy it all, and then packs it up in a new Box to return to the caller. The free function converts the raw pointer back to a Box, and then lets the <em>Drop<\/em> implementation of Box take care of freeing all memory related to it.<\/p>\n<h5>Actual Functionality<\/h5>\n<p>The two remaining functions are C wrappers for the <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\/imp.rs#L58-L72\" target=\"_blank\">get() and set()<\/a> Rust functions:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_rstring_get(rstring: *const RString) -&gt; *mut c_char {\r\n    callback_guard!();\r\n\r\n    let rstring = &amp;*rstring;\r\n    rstring.get().to_glib_full()\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_rstring_set(rstring: *mut RString, s: *const c_char) {\r\n    callback_guard!();\r\n\r\n    let rstring = &amp;mut *rstring;\r\n    rstring.set(from_glib_none(s));\r\n}<\/pre>\n<p>These only call the corresponding Rust functions. The <em>set()<\/em> function again uses glib&#8217;s <em>from_glib_none()<\/em> to convert from a C string to a Rust string. The <em>get()<\/em> function uses <em>ToGlibPtrFull::to_glib_full()<\/em> from GLib to convert from a Rust string (<em>Option<String><\/em> to be accurate) to a C string, while passing ownership of the C string to the caller (which then also has to free it at a later time).<\/p>\n<p>This was all quite verbose, which is why a macro based solution for all this would be very helpful.<\/p>\n<h5>Corresponding C Header<\/h5>\n<p>Now if this API would be used from C, the header file to do so would look something like <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/include\/ex\/rstring.h\" target=\"_blank\">this<\/a>. Probably no surprises here.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-title=\"\">#define EX_TYPE_RSTRING            (ex_rstring_get_type())\r\n\r\ntypedef struct _ExRString          ExRString;\r\n\r\nGType       ex_rstring_get_type    (void);\r\n\r\nExRString * ex_rstring_new         (const gchar * s);\r\nExRString * ex_rstring_copy        (const ExRString * rstring);\r\nvoid        ex_rstring_free        (ExRString * rstring);\r\ngchar *     ex_rstring_get         (const ExRString * rstring);\r\nvoid        ex_rstring_set         (ExRString *rstring, const gchar *s);<\/pre>\n<p>Ideally this would also be autogenerated from the Rust code in one way or another, maybe via <a href=\"https:\/\/github.com\/Sean1708\/rusty-cheddar\" target=\"_blank\">rusty-cheddar<\/a> or <a href=\"https:\/\/gitlab.com\/rusty-binder\/rusty-binder\" target=\"_blank\">rusty-binder<\/a>.<\/p>\n<h4>SharedRString<\/h4>\n<p>The shared, reference counted, RString works basically the same. The only differences are in how the pointers between C and Rust are converted. For this, let&#8217;s take a look at the <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/shared_rstring\/imp.rs#L31-L37\" target=\"_blank\">constructor<\/a>, <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/shared_rstring\/imp.rs#L39-L52\" target=\"_blank\">copy<\/a> (aka ref) and <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/shared_rstring\/imp.rs#L54-L59\" target=\"_blank\">free<\/a> (aka unref) functions again:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_shared_rstring_new(s: *const c_char) -&gt; *mut SharedRString {\r\n    callback_guard!();\r\n\r\n    let s = SharedRString::new(from_glib_none(s));\r\n    Arc::into_raw(s) as *mut _\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_shared_rstring_ref(\r\n    shared_rstring: *mut SharedRString,\r\n) -&gt; *mut SharedRString {\r\n    callback_guard!();\r\n\r\n    let shared_rstring = Arc::from_raw(shared_rstring);\r\n    let s = shared_rstring.clone();\r\n\r\n    \/\/ Forget it and keep it alive, we will still need it later\r\n    let _ = Arc::into_raw(shared_rstring);\r\n\r\n    Arc::into_raw(s) as *mut _\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_shared_rstring_unref(shared_rstring: *mut SharedRString) {\r\n    callback_guard!();\r\n\r\n    let _ = Arc::from_raw(shared_rstring);\r\n}<\/pre>\n<p>The only difference here is that instead of using a Box, <a href=\"https:\/\/doc.rust-lang.org\/stable\/alloc\/arc\/struct.Arc.html\" target=\"_blank\"><em>std::alloc::Arc<\/em><\/a> is used, and some differences in the copy (aka ref) function. Previously with the Box, we were just creating a immutable reference from the raw pointer and cloned it, but with the Arc we want to clone the Arc itself (i.e. have the same underlying object but increase the reference count). For this we use <em>Arc::from_raw()<\/em> to get back an Arc, and then clone the Arc. If we wouldn&#8217;t do anything else, at the end of the function our original Arc would get its <em>Drop<\/em> implementation called and the reference count decreased, defeating the whole point of the function. To prevent that, we convert the original Arc to a raw pointer again and &#8220;leak&#8221; it. That is, we don&#8217;t destroy the reference owned by the caller, which would cause double free problems later.<\/p>\n<p>Apart from this, everything is really the same. And also <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/include\/ex\/shared-rstring.h\" target=\"_blank\">the C header<\/a> looks basically the same.<\/p>\n<h3 id=\"objects\">Object types<\/h3>\n<p>Now let&#8217;s start with the more interesting part: actual subclasses of GObject with all the features you know from object-oriented languages. Everything up to here was only warm-up, even if useful by itself already to expose normal Rust types to C with a slightly more expressive API.<\/p>\n<p>In GObject, subclasses of the GObject base class (think of Object in Java or C#, the most basic type from which everything inherits) all get the main following features from the base class: reference counting, inheritance, virtual methods, properties, signals. Similarly to boxed types, some functions and structs are registered at runtime with the GObject library to get back a type ID but it is slightly more involved. And our structs must be <em>#[repr(C)]<\/em> and be structured in a very specific way.<\/p>\n<h5>Struct Definitions<\/h5>\n<p>Every GObject subclass has <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L19-L33\" target=\"_blank\">two structs<\/a>: 1) one instance struct that is used for the memory layout of every instance and could contain public fields, and 2) one class struct which is storing the class specific data and the instance struct contains a pointer to it. The class struct is more or less what in C++ the vtable would be, i.e. the place where virtual methods are stored, but in GObject it can also contain fields for example. We define a new type <em>Foo<\/em> that inherits from <em>GObject<\/em>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[repr(C)]\r\npub struct Foo {\r\n    pub parent: gobject_ffi::GObject,\r\n}\r\n\r\n#[repr(C)]\r\npub struct FooClass {\r\n    pub parent_class: gobject_ffi::GObjectClass,\r\n}<\/pre>\n<p>The first element of the structs must be the corresponding struct of the class we inherit from. This later allows casting pointers of our subclass to pointers of the base class, and re-use all API implemented for the base class. In our example here we don&#8217;t define any public fields or virtual methods, in the repository the version has them but we get to that later.<\/p>\n<p>Now we will actually need to be able to store some state with our objects, but we want to have that state private. For that we <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L50-L54\" target=\"_blank\">define another struct<\/a>, a plain Rust struct this time<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">struct FooPrivate {\r\n    name: RefCell&lt;Option&lt;String&gt;&gt;,\r\n    counter: RefCell&lt;i32&gt;,\r\n}<\/pre>\n<p>This uses <em>RefCell<\/em> for each field, as in GObject modifications of objects are all done conceptually via interior mutability. For a thread-safe object these would have to be <em>Mutex<\/em> instead.<\/p>\n<h5>Type Registration<\/h5>\n<p>In the end we glue all this together and register it to the GObject type system via a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L385-L429\" target=\"_blank\"><em>get_type()<\/em> function<\/a>, similar to the one for boxed types<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_foo_get_type() -&gt; glib_ffi::GType {\r\n    callback_guard!();\r\n\r\n    static mut TYPE: glib_ffi::GType = gobject_ffi::G_TYPE_INVALID;\r\n    static ONCE: Once = ONCE_INIT;\r\n\r\n    ONCE.call_once(|| {\r\n        let type_info = gobject_ffi::GTypeInfo {\r\n            class_size: mem::size_of::&lt;FooClass&gt;() as u16,\r\n            base_init: None,\r\n            base_finalize: None,\r\n            class_init: Some(FooClass::init),\r\n            class_finalize: None,\r\n            class_data: ptr::null(),\r\n            instance_size: mem::size_of::&lt;Foo&gt;() as u16,\r\n            n_preallocs: 0,\r\n            instance_init: Some(Foo::init),\r\n            value_table: ptr::null(),\r\n        };\r\n\r\n        let type_name = CString::new(&quot;ExFoo&quot;).unwrap();\r\n\r\n        TYPE = gobject_ffi::g_type_register_static(\r\n            gobject_ffi::g_object_get_type(),\r\n            type_name.as_ptr(),\r\n            &amp;type_info,\r\n            gobject_ffi::GTypeFlags::empty(),\r\n        );\r\n    });\r\n\r\n    TYPE\r\n}<\/pre>\n<p>The main difference here is that we call <em>g_type_register_static()<\/em>, which takes a struct as parameter that contains all the information about our new subclass. In that struct we provide sizes of the class and instance struct (GObject is allocating them for us), various uninteresting fields for now and two function pointers: 1) <em>class_init<\/em> for initializing the class struct as allocated by GObject (here we would also override virtual methods, define signals or properties for example) and 2) <em>instance_init<\/em> to do the same with the instance struct. Both structs are zero-initialized in the parts we defined, and the parent parts of both structs are initialized by the code for the parent class already.<\/p>\n<h5>Struct Initialization<\/h5>\n<p>These two functions look <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L89-L108\" target=\"_blank\">like the<\/a> <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L241-L313\" target=\"_blank\">following<\/a> for us (the versions in the repository already do more things)<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl Foo {\r\n    unsafe extern &quot;C&quot; fn init(obj: *mut gobject_ffi::GTypeInstance, _klass: glib_ffi::gpointer) {\r\n        callback_guard!();\r\n\r\n        let private = gobject_ffi::g_type_instance_get_private(\r\n            obj as *mut gobject_ffi::GTypeInstance,\r\n            ex_foo_get_type(),\r\n        ) as *mut Option&lt;FooPrivate&gt;;\r\n\r\n        \/\/ Here we initialize the private data. By default it is all zero-initialized\r\n        \/\/ but we don&#039;t really want to have any Drop impls run here so just overwrite the\r\n        \/\/ data\r\n        ptr::write(\r\n            private,\r\n            Some(FooPrivate {\r\n                name: RefCell::new(None),\r\n                counter: RefCell::new(0),\r\n            }),\r\n        );\r\n    }\r\n}\r\n\r\nimpl FooClass {\r\n    unsafe extern &quot;C&quot; fn init(klass: glib_ffi::gpointer, _klass_data: glib_ffi::gpointer) {\r\n        callback_guard!();\r\n\r\n        \/\/ This is an Option&lt;_&gt; so that we can replace its value with None on finalize() to\r\n        \/\/ release all memory it holds\r\n        gobject_ffi::g_type_class_add_private(klass, mem::size_of::&lt;Option&lt;FooPrivate&gt;&gt;() as usize);\r\n    }\r\n}<\/pre>\n<p>During class initialization, we tell GObject about the size of our private struct but we actually wrap it into an <em>Option<\/em>. This allows us to later replace it simply with <em>None<\/em> to deallocate all memory related to it. During instance initialization this private struct is already allocated for us by GObject (and zero-initialized), so we simply get a raw pointer to it via <em>g_type_instance_get_private()<\/em> and write an initialized struct to that pointer. Raw pointers must be used here so that the <em>Drop<\/em> implementation of <em>Option<\/em> is not called for the old, zero-initialized memory when replacing the struct.<\/p>\n<p>As you might&#8217;ve noticed, we currently never set the private struct to <em>None<\/em> to release the memory, effectively leaking memory, but we get to that later when talking about virtual methods.<\/p>\n<h5>Constructor<\/h5>\n<p>With what we have so far, it&#8217;s already possible to create new instances of our subclass, and for that we also define a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L358-L383\" target=\"_blank\">constructor function<\/a> now<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_foo_new() -&gt; *mut Foo {\r\n    callback_guard!();\r\n\r\n    let this = gobject_ffi::g_object_newv(\r\n        ex_foo_get_type(),\r\n        0,\r\n        ptr::null_mut(),\r\n    );\r\n\r\n    this as *mut Foo\r\n}<\/pre>\n<p>There is probably not much that has to be explained here: we only tell GObject to allocate a new instance of our specific type (by providing the type ID), which then causes the memory to be allocated and our initialization functions to be called. For the very first time, class_init would be called, for all times instance_init is called.<\/p>\n<h5>Methods<\/h5>\n<p>All this would be rather boring at this point because there is no way to actually do something with our object, so various functions are defined to work with the private data. For example to <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L338-L346\" target=\"_blank\">get the<\/a> <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L217-L219\" target=\"_blank\">value o<\/a>f the counter<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"default\" data-enlighter-title=\"\">impl Foo {\r\n    fn get_counter(_this: &amp;FooWrapper, private: &amp;FooPrivate) -&gt; i32 {\r\n        *private.counter.borrow()\r\n    }\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_foo_get_counter(this: *mut Foo) -&gt; i32 {\r\n    callback_guard!();\r\n\r\n    let private = (*this).get_priv();\r\n\r\n    Foo::get_counter(&amp;from_glib_borrow(this), private)\r\n}<\/pre>\n<p>This gets the private struct from GObject (<em>get_priv()<\/em> is a helper function that does the same as we did in instance_init), and then calls a safe Rust function implemented on our struct to actually get the value. Notable here is that we don&#8217;t pass <em>&#038;self<\/em> to the function, but something called <em>FooWrapper<\/em>. This is a GTK-rs style wrapper type that directly allows to use any API implemented on parent classes and provides various other functionality. It is defined in <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/mod.rs\" target=\"_blank\"><em>mod.rs<\/em><\/a> but we will talk about that later.<\/p>\n<h4 id=\"inheritance\">Inheritance<\/h3>\n<p>GObject allows single-inheritance from a base class, similar to Java and C#. All behaviour of the base class is inherited, and API of the base class can be used on the subclass.<\/p>\n<p>I shortly hinted at how that works above already: 1) instance and class struct have the parent class&#8217; structs as first field, so casting to pointers of the parent class work just fine, 2) GObject is told what the parent class is in the call to <em>g_type_register_static()<\/em>. We did that above already, as we inherited from <em>GObject<\/em>.<\/p>\n<p>By inheriting from <em>GObject<\/em>, we e.g. can call <em>g_object_ref()<\/em> to do reference counting, or any of the other GObject API. Also it allows the Rust wrapper type defined in <em>mod.rs<\/em> to provide appropriate API for the base class to us without any casts, and to do memory management automatically. How that works is probably going to be explained in one of the following blog posts on <a href=\"https:\/\/people.gnome.org\/~federico\/blog\/how-glib-rs-works-part-2.html\" target=\"_blank\">Federico&#8217;s blog<\/a>.<\/p>\n<p>In the example repository, there is also another type defined which inherits from our type <em>Foo<\/em>, called <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/tree\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/bar\" target=\"_blank\"><em>Bar<\/em><\/a>. It&#8217;s basically the same code again, except for the name and parent type.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[repr(C)]\r\npub struct Bar {\r\n    pub parent: foo::imp::Foo,\r\n}\r\n\r\n#[repr(C)]\r\npub struct BarClass {\r\n    pub parent_class: foo::imp::FooClass,\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_bar_get_type() -&gt; glib_ffi::GType {\r\n    [...]\r\n        TYPE = gobject_ffi::g_type_register_static(\r\n            foo::imp::ex_foo_get_type(),\r\n            type_name.as_ptr(),\r\n            &amp;type_info,\r\n            gobject_ffi::GTypeFlags::empty(),\r\n        );\r\n    [...]\r\n}<\/pre>\n<h4 id=\"vfuncs\">Virtual Methods<\/h3>\n<h5>Overriding Virtual Methods<\/h5>\n<p>Inheritance alone is already useful for reducing code duplication, but to make it really useful <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/howto-gobject-methods.html#virtual-public-methods\" target=\"_blank\">virtual methods<\/a> are needed so that behaviour can be adjusted. In GObject this works similar to how it&#8217;s done in e.g. C++, just manually: you place function pointers to the virtual method implementations into the class struct and then call those. As every subclass has its own copy of the class struct (initialized with the values from the parent class), it can override these with whatever function it wants. And as it&#8217;s possible to get the actual class struct of the parent class, it is possible to chain up to the implementation of the virtual function of the parent class. Let&#8217;s look at the example of the <em>GObject::finalize<\/em> virtual method, which is called at the very end when the object is to be destroyed and which should free all memory. In there we will free our private data struct with the RefCells.<\/p>\n<p>As a first step, we need to override the function pointer in the class struct <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L251-L252\" target=\"_blank\">in our class_init function<\/a> and replace it with <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L113-L124\" target=\"_blank\">another function<\/a> that implements the behaviour we want<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl FooClass {\r\n    unsafe extern &quot;C&quot; fn init(klass: glib_ffi::gpointer, _klass_data: glib_ffi::gpointer) {\r\n        [...]\r\n        {\r\n            let gobject_klass = &amp;mut *(klass as *mut gobject_ffi::GObjectClass);\r\n            gobject_klass.finalize = Some(Foo::finalize);\r\n        }\r\n        [...]\r\n    }\r\n}\r\n\r\nimpl Foo {\r\n    unsafe extern &quot;C&quot; fn finalize(obj: *mut gobject_ffi::GObject) {\r\n        callback_guard!();\r\n\r\n        \/\/ Free private data by replacing it with None\r\n        let private = gobject_ffi::g_type_instance_get_private(\r\n            obj as *mut gobject_ffi::GTypeInstance,\r\n            ex_foo_get_type(),\r\n        ) as *mut Option&lt;FooPrivate&gt;;\r\n        let _ = (*private).take();\r\n\r\n        (*PRIV.parent_class).finalize.map(|f| f(obj));\r\n    }\r\n}<\/pre>\n<p>This new function could call into a safe Rust implementation, like it&#8217;s done for other virtual methods (see a bit later) but for <em>finalize<\/em> we have to do manual memory management and that&#8217;s all unsafe Rust. The way how we free the memory here is by replacing, that is <em>take()<\/em>ing the <em>Some<\/em> value out of the <em>Option<\/em> that contains our private struct, and then let it be dropped. Afterwards we have to <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/howto-gobject-chainup.html\" target=\"_blank\">chain up to the parent class&#8217;<\/a> implementation of finalize, which is done by calling <em>map()<\/em> on the <em>Option<\/em> that contains the function pointer.<\/p>\n<p>All the function pointers in <em>glib-sys<\/em> and related crates is stored in <em>Option<\/em>s to be able to handle the case of a NULL function pointer and an actual function pointer to a function.<\/p>\n<p>Now for chaining up to the parent class&#8217; finalize implementation, there&#8217;s a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L56-L67\" target=\"_blank\"><em>static<\/em>, global variable<\/a> containing a pointer to the parent class&#8217; class struct, called <em>PRIV<\/em>. This is also <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L311-L312\" target=\"_blank\">initialized in the class_init<\/a> function<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">struct FooClassPrivate {\r\n    parent_class: *const gobject_ffi::GObjectClass,\r\n}\r\nstatic mut PRIV: FooClassPrivate = FooClassPrivate {\r\n    parent_class: 0 as *const _,\r\n};\r\n\r\nimpl FooClass {\r\n    unsafe extern &quot;C&quot; fn init(klass: glib_ffi::gpointer, _klass_data: glib_ffi::gpointer) {\r\n        [...]\r\n        PRIV.parent_class =\r\n            gobject_ffi::g_type_class_peek_parent(klass) as *const gobject_ffi::GObjectClass;\r\n    }\r\n}<\/pre>\n<p>While this is a <em>static mut<\/em> global variable, this is fine as it&#8217;s only ever written to once from class_init, and can only ever be accessed after class_init is done.<\/p>\n<h5>Defining New Virtual Methods<\/h5>\n<p>For defining new virtual methods, we would add a corresponding function pointer <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L31\" target=\"_blank\">to the class struct<\/a> and optionally initialize it to a default implementation <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L281\" target=\"_blank\">in the class_init function<\/a>, or otherwise keep it at NULL\/None.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[repr(C)]\r\npub struct FooClass {\r\n    pub parent_class: gobject_ffi::GObjectClass,\r\n    pub increment: Option&lt;unsafe extern &quot;C&quot; fn(*mut Foo, inc: i32) -&gt; i32&gt;,\r\n}\r\n\r\nimpl FooClass {\r\n    unsafe extern &quot;C&quot; fn init(klass: glib_ffi::gpointer, _klass_data: glib_ffi::gpointer) {\r\n        {\r\n            let foo_klass = &amp;mut *(klass as *mut FooClass);\r\n            foo_klass.increment = Some(Foo::increment_trampoline);\r\n        }\r\n    }\r\n}<\/pre>\n<p>The <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L173-L179\" target=\"_blank\">trampoline function<\/a> provided here is responsible for converting from the C types to the Rust types, and then calling a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L192-L210\" target=\"_blank\">safe Rust implementation<\/a> of the virtual method.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl Foo {\r\n    unsafe extern &quot;C&quot; fn increment_trampoline(this: *mut Foo, inc: i32) -&gt; i32 {\r\n        callback_guard!();\r\n\r\n        let private = (*this).get_priv();\r\n\r\n        Foo::increment(&amp;from_glib_borrow(this), private, inc)\r\n    }\r\n\r\n    fn increment(this: &amp;FooWrapper, private: &amp;FooPrivate, inc: i32) -&gt; i32 {\r\n        let mut val = private.counter.borrow_mut();\r\n\r\n        *val += inc;\r\n\r\n        *val\r\n    }\r\n}<\/pre>\n<p>To make it possible to call these virtual methods from the outside, a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L329-L336\" target=\"_blank\">C function has to be defined<\/a> again similar to the ones for non-virtual methods. Instead of calling the Rust implementation directly, this gets the class struct of the type that is passed in and then calls the function pointer for the virtual method implementation of that specific type.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_foo_increment(this: *mut Foo, inc: i32) -&gt; i32 {\r\n    callback_guard!();\r\n\r\n    let klass = (*this).get_class();\r\n\r\n    (klass.increment.as_ref().unwrap())(this, inc)\r\n}<\/pre>\n<p>Subclasses <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/bar\/imp.rs#L160-L180\" target=\"_blank\">would override<\/a> <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/bar\/imp.rs#L240\" target=\"_blank\">this default implementation<\/a> (or provide an actual implementation) exactly the same way, and also chain up to the parent class&#8217; implementation like we saw before for <em>GObject::finalize<\/em>.<\/p>\n<h4 id=\"properties\">Properties<\/h3>\n<p>Similar to Objective-C and C#, GObject has support for <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/gobject-properties.html\" target=\"_blank\">properties<\/a>. These are registered per type, have some metadata attached to them (property type, name, description, writability, valid value range, etc) and subclasses are inheriting them and can override them. The main difference between properties and struct fields is that setting\/getting the property values is executing some code instead of just pointing at a memory location, and you can connect a callback to the property to be notified whenever its value changes. And they can be queried at runtime from a specific type, and set\/get via their string names instead of actual C API. Allowed types for properties are everything that has a GObject type ID assigned, including all GObject subclasses, many fundamental types (integers, strings, &#8230;) and boxed types like our RString and SharedRString above.<\/p>\n<h5>Defining Properties<\/h5>\n<p>To define a property, we have to register it in the class_init function and also implement the <em>GObject::get_property()<\/em> and <em>GObject::set_property()<\/em> virtual methods (or only one of them for read-only \/ write-only properties). Internally inside the implementation of our GObject, the properties are identified by an integer index for which we define a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L35-L38\" target=\"_blank\">simple enum<\/a>, and when registered we get back a <em>GParamSpec<\/em> pointer that we should <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L60\" target=\"_blank\">also store<\/a> (for notifying about property changes for example).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[repr(u32)]\r\nenum Properties {\r\n    Name = 1,\r\n}\r\n\r\nstruct FooClassPrivate {\r\n    parent_class: *const gobject_ffi::GObjectClass,\r\n    properties: *const Vec&lt;*const gobject_ffi::GParamSpec&gt;,\r\n}\r\nstatic mut PRIV: FooClassPrivate = FooClassPrivate {\r\n    parent_class: 0 as *const _,\r\n    properties: 0 as *const _,\r\n};<\/pre>\n<p><a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L250-L277\" target=\"_blank\">In class_init<\/a> we then override the two virtual methods and register a new property, by providing the name, type, value of our enum corresponding to that property, default value and various other metadata. We then store the <em>GParamSpec<\/em> related to the property in a <em>Vec<\/em>, indexed by the enum value. In our example we add a string-typed &#8220;name&#8221; property that is readable and writable, but can only ever be written to during object construction.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl FooClass {\r\n    \/\/ Class struct initialization, called from GObject\r\nunsafe extern &quot;C&quot; fn init(klass: glib_ffi::gpointer, _klass_data: glib_ffi::gpointer) {\r\n    {\r\n        [...]\r\n        {\r\n            let gobject_klass = &amp;mut *(klass as *mut gobject_ffi::GObjectClass);\r\n            gobject_klass.finalize = Some(Foo::finalize);\r\n            gobject_klass.set_property = Some(Foo::set_property);\r\n            gobject_klass.get_property = Some(Foo::get_property);\r\n\r\n            let mut properties = Vec::new();\r\n\r\n            let name_cstr = CString::new(&quot;name&quot;).unwrap();\r\n            let nick_cstr = CString::new(&quot;Name&quot;).unwrap();\r\n            let blurb_cstr = CString::new(&quot;Name of the object&quot;).unwrap();\r\n\r\n            properties.push(ptr::null());\r\n            properties.push(gobject_ffi::g_param_spec_string(\r\n                name_cstr.as_ptr(),\r\n                nick_cstr.as_ptr(),\r\n                blurb_cstr.as_ptr(),\r\n                ptr::null_mut(),\r\n                gobject_ffi::G_PARAM_READWRITE | gobject_ffi::G_PARAM_CONSTRUCT_ONLY,\r\n            ));\r\n            gobject_ffi::g_object_class_install_properties(\r\n                gobject_klass,\r\n                properties.len() as u32,\r\n                properties.as_mut_ptr() as *mut *mut _,\r\n            );\r\n\r\n            PRIV.properties = Box::into_raw(Box::new(properties));\r\n        }\r\n    }\r\n}<\/pre>\n<p>Afterwards we define the <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L126-L171\" target=\"_blank\">trampoline implementations<\/a> for the <em>set_property<\/em> and <em>get_property<\/em> virtual methods.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl Foo {\r\n    unsafe extern &quot;C&quot; fn set_property(\r\n        obj: *mut gobject_ffi::GObject,\r\n        id: u32,\r\n        value: *mut gobject_ffi::GValue,\r\n        _pspec: *mut gobject_ffi::GParamSpec,\r\n    ) {\r\n        callback_guard!();\r\n\r\n        let this = &amp;*(obj as *mut Foo);\r\n        let private = (*this).get_priv();\r\n\r\n        \/\/ FIXME: How to get rid of the transmute?\r\n        match mem::transmute::&lt;u32, Properties&gt;(id) {\r\n            Properties::Name =&gt; {\r\n                \/\/ FIXME: Need impl FromGlibPtrBorrow for Value\r\n                let name = gobject_ffi::g_value_get_string(value);\r\n                Foo::set_name(\r\n                    &amp;from_glib_borrow(obj as *mut Foo),\r\n                    private,\r\n                    from_glib_none(name),\r\n                );\r\n            }\r\n            _ =&gt; unreachable!(),\r\n        }\r\n    }\r\n\r\n    unsafe extern &quot;C&quot; fn get_property(\r\n        obj: *mut gobject_ffi::GObject,\r\n        id: u32,\r\n        value: *mut gobject_ffi::GValue,\r\n        _pspec: *mut gobject_ffi::GParamSpec,\r\n    ) {\r\n        callback_guard!();\r\n\r\n        let private = (*(obj as *mut Foo)).get_priv();\r\n\r\n        \/\/ FIXME: How to get rid of the transmute?\r\n        match mem::transmute::&lt;u32, Properties&gt;(id) {\r\n            Properties::Name =&gt; {\r\n                let name = Foo::get_name(&amp;from_glib_borrow(obj as *mut Foo), private);\r\n                \/\/ FIXME: Need impl FromGlibPtrBorrow for Value\r\n                gobject_ffi::g_value_set_string(value, name.to_glib_none().0);\r\n            }\r\n            _ =&gt; unreachable!(),\r\n        }\r\n    }\r\n}<\/pre>\n<p>In there we decide based on the index which property is meant, and then convert from\/to the <em>GValue<\/em> container provided by GObject, and then call <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L221-L227\" target=\"_blank\">into safe Rust getters\/setters<\/a>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl Foo {\r\n    fn get_name(_this: &amp;FooWrapper, private: &amp;FooPrivate) -&gt; Option&lt;String&gt; {\r\n        private.name.borrow().clone()\r\n    }\r\n\r\n    fn set_name(_this: &amp;FooWrapper, private: &amp;FooPrivate, name: Option&lt;String&gt;) {\r\n        *private.name.borrow_mut() = name;\r\n    }\r\n}<\/pre>\n<p>This property can now be used via the GObject API, e.g. its value can be retrieved via <em>g_object_get(obj, &#8220;name&#8221;, &#038;pointer_to_a_char_pointer)<\/em> in C.<\/p>\n<h5>Construct Properties<\/h5>\n<p>The property we defined above had one special feature: it can only ever be set during object construction. Similarly, every property that is writable can also be set during object construction. This works by providing a value to <em>g_object_new()<\/em> <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L358-L383\" target=\"_blank\">in the constructor function<\/a>, which then causes GObject to pass this to our <em>set_property()<\/em> implementation.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_foo_new(name: *const c_char) -&gt; *mut Foo {\r\n    callback_guard!();\r\n\r\n    let prop_name_name = &quot;name&quot;.to_glib_none();\r\n    let prop_name_str: Option&lt;String&gt; = from_glib_none(name);\r\n    let prop_name_value = glib::Value::from(prop_name_str.as_ref());\r\n\r\n    let mut properties = [\r\n        gobject_ffi::GParameter {\r\n            name: prop_name_name.0,\r\n            value: prop_name_value.into_raw(),\r\n        },\r\n    ];\r\n    let this = gobject_ffi::g_object_newv(\r\n        ex_foo_get_type(),\r\n        properties.len() as u32,\r\n        properties.as_mut_ptr(),\r\n    );\r\n\r\n    gobject_ffi::g_value_unset(&amp;mut properties[0].value);\r\n\r\n    this as *mut Foo\r\n}<\/pre>\n<h4 id=\"signals\">Signals<\/h3>\n<p>GObject also supports <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/howto-signals.html\" target=\"_blank\">signals<\/a>. These are similar to events in e.g. C#, Qt or the C++ Boost signals library, and not to be confused with <a href=\"https:\/\/en.wikipedia.org\/wiki\/Signal_(IPC)\" target=\"_blank\">UNIX signals<\/a>. GObject signals allow you to connect a callback that is called every time a specific event happens.<\/p>\n<h5>Signal Registration<\/h5>\n<p>Similarly to properties, these are registered in class_init together with various metadata, can be queried at runtime and are usually used by string name. Notification about property changes is implemented with signals, the <em>GObject::notify<\/em> signal.<\/p>\n<p>Also similarly to properties, internally in our implementation the signals are used by an integer index. We also <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L56-L67\" target=\"_blank\">store that globally<\/a>, indexed by a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L40-L43\" target=\"_blank\">simple enum<\/a>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[repr(u32)]\r\nenum Signals {\r\n    Incremented = 0,\r\n}\r\n\r\nstruct FooClassPrivate {\r\n    parent_class: *const gobject_ffi::GObjectClass,\r\n    properties: *const Vec&lt;*const gobject_ffi::GParamSpec&gt;,\r\n    signals: *const Vec&lt;u32&gt;,\r\n}\r\nstatic mut PRIV: FooClassPrivate = FooClassPrivate {\r\n    parent_class: 0 as *const _,\r\n    properties: 0 as *const _,\r\n    signals: 0 as *const _,\r\n};<\/pre>\n<p><a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L285-L309\" target=\"_blank\">In class_init<\/a> we then register the signal for our type. For that we provide a name, the parameters of the signal (anything that can be stored in a <em>GValue<\/em> can be used for this again), the return value (we don&#8217;t have one here) and various other metadata. GObject then tells us the ID of the signal, which we store in our vector. In our case we define a signal named &#8220;incremented&#8221;, that is emitted every time the internal counter of the object is incremented and provides the current value of the counter and by how much it was incremented.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl FooClass {\r\n    \/\/ Class struct initialization, called from GObject\r\nunsafe extern &quot;C&quot; fn init(klass: glib_ffi::gpointer, _klass_data: glib_ffi::gpointer) {\r\n        [...]\r\n        let mut signals = Vec::new();\r\n\r\n        let name_cstr = CString::new(&quot;incremented&quot;).unwrap();\r\n        let param_types = [gobject_ffi::G_TYPE_INT, gobject_ffi::G_TYPE_INT];\r\n\r\n        \/\/ FIXME: Is there a better way?\r\n        let class_offset = {\r\n            let dummy: FooClass = mem::uninitialized();\r\n            ((&amp;dummy.incremented as *const _ as usize) - (&amp;dummy as *const _ as usize)) as u32\r\n        };\r\n\r\n        signals.push(gobject_ffi::g_signal_newv(\r\n            name_cstr.as_ptr(),\r\n            ex_foo_get_type(),\r\n            gobject_ffi::G_SIGNAL_RUN_LAST,\r\n            gobject_ffi::g_signal_type_cclosure_new(ex_foo_get_type(), class_offset),\r\n            None,\r\n            ptr::null_mut(),\r\n            None,\r\n            gobject_ffi::G_TYPE_NONE,\r\n            param_types.len() as u32,\r\n            param_types.as_ptr() as *mut _,\r\n        ));\r\n\r\n        PRIV.signals = Box::into_raw(Box::new(signals));\r\n    }\r\n}<\/pre>\n<p>One special part here is the <em>class_offset<\/em>. GObject allows to (optionally) define a default class handler for the signal. This is always called when the signal is emitted, and is usually <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L32\" target=\"_blank\">a virtual method<\/a> <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L181-L187\" target=\"_blank\">that can be overridden<\/a> by subclasses. During signal registration, the offset in bytes to the function pointer of that virtual method inside the class struct is provided.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">#[repr(C)]\r\npub struct FooClass {\r\n    pub parent_class: gobject_ffi::GObjectClass,\r\n    pub increment: Option&lt;unsafe extern &quot;C&quot; fn(*mut Foo, inc: i32) -&gt; i32&gt;,\r\n    pub incremented: Option&lt;unsafe extern &quot;C&quot; fn(*mut Foo, val: i32, inc: i32)&gt;,\r\n}\r\n\r\nimpl Foo {\r\n    unsafe extern &quot;C&quot; fn incremented_trampoline(this: *mut Foo, val: i32, inc: i32) {\r\n        callback_guard!();\r\n\r\n        let private = (*this).get_priv();\r\n\r\n        Foo::incremented(&amp;from_glib_borrow(this), private, val, inc);\r\n    }\r\n\r\n    fn incremented(_this: &amp;FooWrapper, _private: &amp;FooPrivate, _val: i32, _inc: i32) {\r\n        \/\/ Could do something here. Default\/class handler of the &quot;incremented&quot;\r\n        \/\/ signal that could be overriden by subclasses\r\n    }\r\n}<\/pre>\n<p>This is all exactly the same as for virtual methods, just that it will be automatically called when the signal is emitted.<\/p>\n<h5>Signal Emission<\/h5>\n<p>For emitting the signal, we have to provide the instance and the arguments in an array as <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/gobject-Generic-values.html\" target=\"_blank\"><em>GValues<\/em><\/a>, and then <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L192-L210\" target=\"_blank\">emit the signal<\/a> by the ID we got back during signal registration.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl Foo {\r\n    fn increment(this: &amp;FooWrapper, private: &amp;FooPrivate, inc: i32) -&gt; i32 {\r\n        let mut val = private.counter.borrow_mut();\r\n\r\n        *val += inc;\r\n\r\n        unsafe {\r\n            let params = [this.to_value(), (*val).to_value(), inc.to_value()];\r\n            gobject_ffi::g_signal_emitv(\r\n                params.as_ptr() as *mut _,\r\n                (*PRIV.signals)[Signals::Incremented as usize],\r\n                0,\r\n                ptr::null_mut(),\r\n            );\r\n        }\r\n\r\n        *val\r\n    }\r\n}<\/pre>\n<p>While all parameters to the signal are provided as a <em>GValue<\/em> here, GObject calls our default class handler and other C callbacks connected to the signal with the corresponding C types directly. The conversion is done inside GObject and then the corresponding function is called via <a href=\"https:\/\/sourceware.org\/libffi\/\" target=\"_blank\">libffi<\/a>. It is also possible to directly get the array of <em>GValues<\/em> instead though, by using the <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/chapter-signal.html#closure\" target=\"_blank\"><em>GClosure<\/em> API<\/a>, for which there are also <a href=\"https:\/\/docs.rs\/glib\/0.3.1\/glib\/closure\/struct.Closure.html\" target=\"_blank\">Rust bindings<\/a>.<\/p>\n<p>Connecting to the signal can now be done via e.g. <em>g_object_connect()<\/em> from C.<\/p>\n<h4 id=\"object-c-header\">C header<\/h3>\n<p>Similarly to the boxed types, we also have to <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/include\/ex\/foo.h\" target=\"_blank\">define a C header<\/a> for the exported GObject C API. This ideally would also be autogenerated from the macro based solution (e.g. with rusty-cheddar), but here we write it manually. This is mostly <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/howto-gobject.html#howto-gobject-header\" target=\"_blank\">GObject boilerplate<\/a> and conventions.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-title=\"\">#include &lt;glib-object.h&gt;\r\n\r\nG_BEGIN_DECLS\r\n\r\n#define EX_TYPE_FOO            (ex_foo_get_type())\r\n#define EX_FOO(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),EX_TYPE_FOO,ExFoo))\r\n#define EX_IS_FOO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),EX_TYPE_FOO))\r\n#define EX_FOO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,EX_TYPE_FOO,ExFooClass))\r\n#define EX_IS_FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,EX_TYPE_FOO))\r\n#define EX_FOO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,EX_TYPE_FOO,ExFooClass))\r\n\r\ntypedef struct _ExFoo      ExFoo;\r\ntypedef struct _ExFooClass ExFooClass;\r\n\r\nstruct _ExFoo {\r\n  GObject parent;\r\n};\r\n\r\nstruct _ExFooClass {\r\n  GObjectClass parent_class;\r\n\r\n  gint (*increment) (ExFoo * foo, gint inc);\r\n  void (*incremented) (ExFoo * foo, gint val, gint inc);\r\n};\r\n\r\nGType   ex_foo_get_type    (void);\r\n\r\nExFoo * ex_foo_new         (const gchar * name);\r\n\r\ngint    ex_foo_increment   (ExFoo * foo, gint inc);\r\ngint    ex_foo_get_counter (ExFoo * foo);\r\ngchar * ex_foo_get_name    (ExFoo * foo);\r\n\r\nG_END_DECLS<\/pre>\n<h3 id=\"interfaces\">Interfaces<\/h3>\n<p>While GObject only allows single inheritance, it provides the ability to implement any number of <a href=\"https:\/\/developer.gnome.org\/gobject\/stable\/gtype-non-instantiable-classed.html\" target=\"_blank\">interfaces<\/a> on a class to provide a common API between independent types. These interfaces are similar to what exists in Java and C#, but similar to Rust traits it is possible to provide default implementations for the interface methods. Also similar to Rust traits, interfaces can declare pre-requisites: interfaces an implementor must also implement, or a base type it must inherit from.<\/p>\n<p>In the repository, a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/tree\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/nameable\" target=\"_blank\"><em>Nameable<\/em><\/a> interface with a <em>get_name()<\/em> method is implemented. Generally it all works exactly the same as with non-interface types and virtual methods. You <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/nameable\/imp.rs#L88-L125\" target=\"_blank\">register a type<\/a> with GObject that inherits from <em>G_TYPE_INTERFACE<\/em>. This type only has a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/nameable\/imp.rs#L22-L26\" target=\"_blank\">class struct<\/a>, no instance struct. And instead of an instance struct, a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/nameable\/imp.rs#L16-L17\" target=\"_blank\">typedef&#8217;d <em>void *<\/em> pointer<\/a> is used. Behind that pointer would be the instance struct of the actual type implementing the interface. A default implementation of methods can be provided the <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/nameable\/imp.rs#L70\" target=\"_blank\">same way as with virtual methods<\/a> in class_init.<\/p>\n<p>There are two main differences though. One is for <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/nameable\/imp.rs#L79-L86\" target=\"_blank\">calling<\/a> an interface method<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">impl Nameable {\r\n    \/\/ Helper functions\r\n    fn get_iface(&amp;self) -&gt; &amp;NameableInterface {\r\n        unsafe {\r\n            let klass = (*(self as *const _ as *const gobject_ffi::GTypeInstance)).g_class;\r\n            let interface =\r\n                gobject_ffi::g_type_interface_peek(klass as *mut c_void, ex_nameable_get_type());\r\n            &amp;*(interface as *const NameableInterface)\r\n        }\r\n    }\r\n}\r\n\r\n#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_nameable_get_name(this: *mut Nameable) -&gt; *mut c_char {\r\n    callback_guard!();\r\n\r\n    let iface = (*this).get_iface();\r\n    iface.get_name.map(|f| f(this)).unwrap_or(ptr::null_mut())\r\n}<\/pre>\n<p>Instead of directly getting the class struct from the instance, we have to call some GObject API to get the interface struct of a specific interface type ID with the virtual methods.<\/p>\n<p>The other difference is for implementation of the interface. Inside the <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L415-L425\" target=\"_blank\"><em>get_type()<\/em><\/a> function a new set of functions is registered, which are <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/imp.rs#L315-L322\" target=\"_blank\">used similar to class_init<\/a> for initialization of the interface struct<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"default\" data-enlighter-title=\"\">#[no_mangle]\r\npub unsafe extern &quot;C&quot; fn ex_foo_get_type() -&gt; glib_ffi::GType {\r\n        [...]\r\n        \/\/ Implement Nameable interface here\r\n        let nameable_info = gobject_ffi::GInterfaceInfo {\r\n            interface_init: Some(FooClass::init_nameable_interface),\r\n            interface_finalize: None,\r\n            interface_data: ptr::null_mut(),\r\n        };\r\n        gobject_ffi::g_type_add_interface_static(\r\n            TYPE,\r\n            ::nameable::imp::ex_nameable_get_type(),\r\n            &amp;nameable_info,\r\n        );\r\n    });\r\n}\r\n\r\nimpl FooClass {\r\n    unsafe extern &quot;C&quot; fn init_nameable_interface(\r\n        iface: glib_ffi::gpointer,\r\n        _iface_data: glib_ffi::gpointer,\r\n    ) {\r\n        let iface = &amp;mut *(iface as *mut ::nameable::imp::NameableInterface);\r\n        iface.get_name = Some(Foo::nameable_get_name_trampoline);\r\n    }\r\n}<\/pre>\n<p>The interface also <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/include\/ex\/nameable.h\" target=\"_blank\">gets a C heade<\/a>r, which looks basically the same as for normal classes.<\/p>\n<h3 id=\"c\">Usage from C<\/h3>\n<p>As mentioned above a few times, we export a normal (GObject) C API. For that various headers have to be written, or ideally be generated later. These can be all found <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/tree\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/include\/ex\" target=\"_blank\">here<\/a>.<\/p>\n<p>Nothing special has to be taken care off for using this API from C, you simply link to the generated shared library, use the headers and then use it like any other GObject based C API.<\/p>\n<h3 id=\"rust\">Usage from Rust<\/h3>\n<p>I mentioned shortly above that in the <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/mod.rs\" target=\"_blank\"><em>mod.rs<\/em><\/a> there are gtk-rs-style Rust bindings. And these are also what would be passed (the &#8220;Wrapper&#8221; arguments) to the safe Rust implementations of the methods.<\/p>\n<p>Ideally these would be autogenerated from a macro, similarly how the <a href=\"https:\/\/github.com\/gtk-rs\/gir\/\" target=\"_blank\">gir<\/a> tool can do already for C based GObject libraries (this is the tool to generate most of the GLib, GTK, etc bindings for Rust).<\/p>\n<p>For usage of those bindings, I&#8217;ll just let <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/foo\/mod.rs#L114-L131\" target=\"_blank\">the code<\/a> <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/fbbf1405d1fc79bdf19f7e855faab1e582f83153\/src\/rstring\/mod.rs#L47-L56\" target=\"_blank\">speak for<\/a> itself<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-title=\"\">    #[test]\r\n    fn test_counter() {\r\n        let foo = Foo::new(Some(&quot;foo&#039;s name&quot;));\r\n\r\n        let incremented = Rc::new(RefCell::new((0i32, 0i32)));\r\n        let incremented_clone = incremented.clone();\r\n        foo.connect_incremented(move |_, val, inc| {\r\n            *incremented_clone.borrow_mut() = (val, inc);\r\n        });\r\n\r\n        assert_eq!(foo.get_counter(), 0);\r\n        assert_eq!(foo.increment(1), 1);\r\n        assert_eq!(*incremented.borrow(), (1, 1));\r\n        assert_eq!(foo.get_counter(), 1);\r\n        assert_eq!(foo.increment(10), 11);\r\n        assert_eq!(*incremented.borrow(), (11, 10));\r\n        assert_eq!(foo.get_counter(), 11);\r\n    }\r\n\r\n    #[test]\r\n    fn test_new() {\r\n        let s = RString::new(Some(&quot;bla&quot;));\r\n        assert_eq!(s.get(), Some(&quot;bla&quot;.into()));\r\n\r\n        let mut s2 = s.clone();\r\n        s2.set(Some(&quot;blabla&quot;));\r\n        assert_eq!(s.get(), Some(&quot;bla&quot;.into()));\r\n        assert_eq!(s2.get(), Some(&quot;blabla&quot;.into()));\r\n    }<\/pre>\n<p>This does automatic memory management, allows to call base-class methods on instances of a subclass, provides access to methods, virtual methods, signals, properties, etc.<\/p>\n<h3 id=\"python-js\">Usage from Python, JavaScript and Others<\/h3>\n<p>Now all this was a lot of boilerplate, but here comes the reason why it is probably all worth it. By exporting a GObject-style C API, we automatically get support for generating bindings for dozens of languages, without having to write any more code. This is possible thanks to the strong API conventions of GObject, and the <a href=\"https:\/\/wiki.gnome.org\/Projects\/GObjectIntrospection\" target=\"_blank\">GObject-Introspection<\/a> project. <a href=\"https:\/\/wiki.gnome.org\/Projects\/GObjectIntrospection\/Users\" target=\"_blank\">Supported languages<\/a> are for example Rust (of course!), <a href=\"https:\/\/pygobject.readthedocs.io\/en\/latest\/\" target=\"_blank\">Python<\/a>, JavaScript (<a href=\"https:\/\/wiki.gnome.org\/Projects\/Gjs\" target=\"_blank\">GJS<\/a> and <a href=\"https:\/\/github.com\/creationix\/node-gir\" target=\"_blank\">Node<\/a>), <a href=\"https:\/\/github.com\/linuxdeepin\/go-gir-generator\" target=\"_blank\">Go<\/a>, C++, <a href=\"http:\/\/www.haskell.org\/haskellwiki\/GObjectIntrospection\" target=\"_blank\">Haskell<\/a>, C#, Perl, PHP, Ruby, &#8230;<\/p>\n<p>GObject-Introspection achieves this by scanning the C headers, introspecting the GObject types and then generating an XML based API description (which also contains information about ownership transfer!). This XML based API description can then be used by code generators for static, compiled bindings (e.g. Rust, Go, Haskell, &#8230;), but it can also be compiled to a so-called &#8220;typelib&#8221;. The typelib provides a C ABI that allows bindings to be generated at runtime, mostly used by scripting languages (e.g. Python and JavaScript).<\/p>\n<p>To show the power of this, I&#8217;ve included a simple <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/master\/test.py\" target=\"_blank\">Python<\/a> and <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/master\/test.js\" target=\"_blank\">JavaScript<\/a> (<a href=\"https:\/\/wiki.gnome.org\/Projects\/Gjs\" target=\"_blank\">GJS<\/a>) application that uses all the types we defined above, and a <a href=\"https:\/\/github.com\/sdroege\/gobject-example-rs\/blob\/master\/Makefile\" target=\"_blank\">Makefile<\/a> that generates the GObject-Introspection metadata and can directly run the Python and JavaScript applications (&#8220;make run-python&#8221; and &#8220;make run-javascript&#8221;).<\/p>\n<p>The Python code looks as follows<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-title=\"\">#! \/usr\/bin\/python3\r\n\r\nimport gi\r\ngi.require_version(&quot;Ex&quot;, &quot;0.1&quot;)\r\nfrom gi.repository import Ex\r\n\r\ndef on_incremented(obj, val, inc):\r\n    print(&quot;incremented to {} by {}&quot;.format(val, inc))\r\n\r\nfoo = Ex.Foo.new(&quot;foo&#039;s name&quot;)\r\nfoo.connect(&quot;incremented&quot;, on_incremented)\r\n\r\nprint(&quot;foo name: &quot; + str(foo.get_name()))\r\nprint(&quot;foo inc 1: &quot; + str(foo.increment(1)))\r\nprint(&quot;foo inc 10: &quot; + str(foo.increment(10)))\r\nprint(&quot;foo counter: &quot; + str(foo.get_counter()))\r\n\r\nbar = Ex.Bar.new(&quot;bar&#039;s name&quot;)\r\nbar.connect(&quot;incremented&quot;, on_incremented)\r\n\r\nprint(&quot;bar name: &quot; + str(bar.get_name()))\r\nprint(&quot;bar inc 1: &quot; + str(bar.increment(1)))\r\nprint(&quot;bar inc 10: &quot; + str(bar.increment(10)))\r\nprint(&quot;bar counter: &quot; + str(bar.get_counter()))\r\n\r\nprint(&quot;bar number: &quot; + str(bar.get_number()))\r\nprint(&quot;bar number (property): &quot; + str(bar.get_property(&quot;number&quot;)))\r\nbar.set_number(10.0)\r\nprint(&quot;bar number: &quot; + str(bar.get_number()))\r\nprint(&quot;bar number (property): &quot; + str(bar.get_property(&quot;number&quot;)))\r\nbar.set_property(&quot;number&quot;, 20.0)\r\nprint(&quot;bar number: &quot; + str(bar.get_number()))\r\nprint(&quot;bar number (property): &quot; + str(bar.get_property(&quot;number&quot;)))\r\n\r\ns = Ex.RString.new(&quot;something&quot;)\r\nprint(&quot;rstring: &quot; + str(s.get()))\r\ns2 = s.copy()\r\ns2.set(&quot;something else&quot;)\r\nprint(&quot;rstring 2: &quot; + str(s2.get()))\r\n\r\ns = Ex.SharedRString.new(&quot;something&quot;)\r\nprint(&quot;shared rstring: &quot; + str(s.get()))\r\ns2 = s.ref()\r\nprint(&quot;shared rstring 2: &quot; + str(s2.get()))<\/pre>\n<p>and the JavaScript (GJS) code as follows<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-title=\"\">#!\/usr\/bin\/gjs\r\n\r\nconst Lang = imports.lang;\r\nconst Ex = imports.gi.Ex;\r\n\r\nlet foo = new Ex.Foo({name: &quot;foo&#039;s name&quot;});\r\nfoo.connect(&quot;incremented&quot;, function(obj, val, inc) {\r\n    print(&quot;incremented to &quot; + val + &quot; by &quot; + inc);\r\n});\r\n\r\nprint(&quot;foo name: &quot; + foo.get_name());\r\nprint(&quot;foo inc 1: &quot; + foo.increment(1));\r\nprint(&quot;foo inc 10: &quot; + foo.increment(10));\r\nprint(&quot;foo counter: &quot; + foo.get_counter());\r\n\r\nlet bar = new Ex.Bar({name: &quot;bar&#039;s name&quot;});\r\nbar.connect(&quot;incremented&quot;, function(obj, val, inc) {\r\n    print(&quot;incremented to &quot; + val + &quot; by &quot; + inc);\r\n});\r\n\r\nprint(&quot;bar name: &quot; + bar.get_name());\r\nprint(&quot;bar inc 1: &quot; + bar.increment(1));\r\nprint(&quot;bar inc 10: &quot; + bar.increment(10));\r\nprint(&quot;bar counter: &quot; + bar.get_counter());\r\n\r\nprint(&quot;bar number: &quot; + bar.get_number());\r\nprint(&quot;bar number (property): &quot; + bar[&quot;number&quot;]);\r\nbar.set_number(10.0)\r\nprint(&quot;bar number: &quot; + bar.get_number());\r\nprint(&quot;bar number (property): &quot; + bar[&quot;number&quot;]);\r\nbar[&quot;number&quot;] = 20.0;\r\nprint(&quot;bar number: &quot; + bar.get_number());\r\nprint(&quot;bar number (property): &quot; + bar[&quot;number&quot;]);\r\n\r\nlet s = new Ex.RString(&quot;something&quot;);\r\nprint(&quot;rstring: &quot; + s.get());\r\nlet s2 = s.copy();\r\ns2.set(&quot;something else&quot;);\r\nprint(&quot;rstring2: &quot; + s2.get());\r\n\r\nlet s = new Ex.SharedRString(&quot;something&quot;);\r\nprint(&quot;shared rstring: &quot; + s.get());\r\nlet s2 = s.ref();\r\nprint(&quot;shared rstring2: &quot; + s2.get());<\/pre>\n<p>Both are doing the same and nothing useful, they simple use all of the available API.<\/p>\n<h3 id=\"what-next\">What next?<\/h3>\n<p>While everything here can be used as-is already (and I use a variation of this in <a href=\"https:\/\/github.com\/sdroege\/gst-plugin-rs\" target=\"_blank\">gst-plugin-rs<\/a>, a crate to write GStreamer plugins in Rust), it&#8217;s rather inconvenient. The goal of this blog post is to have a low-level explanation about how all this works in GObject with Rust, and to have a &#8220;template&#8221; to use for <a href=\"https:\/\/github.com\/nikomatsakis\/gnome-class\" target=\"_blank\">Nikos&#8217; gnome-class<\/a> macro. <a href=\"https:\/\/people.gnome.org\/~federico\/blog\/index.html\" target=\"_blank\">Federico<\/a> is planning to work on this in the near future, and step by step move features from my repository to the macro. Work on this will also be done at the <a href=\"https:\/\/wiki.gnome.org\/Hackfests\/Rust2017-2\" target=\"_blank\">GNOME\/Rust hackfest in November in Berlin<\/a>, which will hopefully yield a lot of progress on the macro but also on the bindings in general.<\/p>\n<p>In the end, this macro would ideally end up in the glib-rs bindings and can then be used directly by anybody to implement GObject subclasses in Rust. At that point, this blog post can hopefully help a bit as documentation to understand how the macro works.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>During the last days I was experimenting a bit with implementing a GObject C API in Rust. The results can be found in this repository, and this is something like an overview of the work, code walkthrough and status report. Note that this is quite long, a little bit further down you can find a &hellip; <a href=\"https:\/\/coaxion.net\/blog\/2017\/09\/exporting-a-gobject-c-api-from-rust-code-and-using-it-from-c-python-javascript-and-others\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Exporting a GObject C API from Rust code and using it from C, Python, JavaScript and others<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,6,53],"tags":[],"class_list":["post-444","post","type-post","status-publish","format-standard","hentry","category-free-software","category-gnome","category-rust"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/posts\/444","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/comments?post=444"}],"version-history":[{"count":39,"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/posts\/444\/revisions"}],"predecessor-version":[{"id":484,"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/posts\/444\/revisions\/484"}],"wp:attachment":[{"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/media?parent=444"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/categories?post=444"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coaxion.net\/blog\/wp-json\/wp\/v2\/tags?post=444"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}