Straw man: moving the GType API down to libglib-2.0

Moved from: https://gitlab.gnome.org/GNOME/glib/-/issues/2370

The type system is not a huge amount of code, and there’s no real need why it should live in libgobject, when a good chunk of types exposed by GLib are boxed in there.

In practical terms, the type system is just a low level API not dissimilar from GVariant. My proposal is to literally move the existing GType and GValue API down one level, with no ABI/API changes; this would allow us to use the type system for the GLib data types out of the box, as well as adding type specialisation to the opaque data containers. We could even add API to GArray/GPtrArray to properly store typed data, and finally replace GValueArray.

The main objection from existing consumers of GLib is that GObject strings along a bunch of additional functionality—signals and properties, closures, etc. We can easily keep those into libgobject-2.0.so; I’d actually insist in keeping them isolated in libgobject, in case we decide to create a new base object class that does not have the known issues of GObject.

The complexity of this surgery is mostly limited to:

  • moving existing GObject/GClosure/GParamSpec initialisers to their own file from gtype-private.h and gtype.c
  • moving gtype.[ch] and gvalue.[ch] and ancillary private files from gobject to glib
  • ensuring that the type system is initialised alongside GLib
  • ensuring that the GObject ancillary types are initialised

Use cases

It’s a big problem we have in GStreamer since the deprecation of GValueArray so any improvement here
would be useful. The basic issue is that some kind of “GArray of GValues” type is needed where it can be known
from the type that it contains GValues, without any secondary, external metadata like annotations.

I assume what @ebassi wants to do here is adding a GType to GArray and GPtrArray so the
element type can be known at runtime.


Adding GType/GValue-based API to GArray, GList, GHashTable, and other data containers without duplicating their internals inside libgobject.

This would also simplify the issue of bindings being unable to deal with transfer rules for data inside container types that have a “clear” function, as the memory management would then be deferred to GType/GValue, just like they are for GObject properties and signal marshallers.

Potential issues

While I think that would be great, I worry about the users of GLib who don’t use GObject. Are you envisaging that they would be able to use GPtrArray (etc.) as before, without type annotations?

They would still not use GObject. To be clear: I’m not suggesting we move GObject to libglib-2.0: only GType and GTypeInstance. The type system by itself isn’t a huge deal; it wouldn’t be problematic for people using only the GLib data structures.

Also, and to be quite blunt: it’s 2021. The objections on the basis of code size made sense 20 years ago, but just like the requirement to use modern toolchains, I find myself struggling to care about people using GLib like it’s 1997, and they only need a bunch of C data types.

Are you envisaging that they would be able to use GPtrArray (etc.) as before, without type annotations?

Yes. I mean: this is an API addition to libglib-2.0.so.

We could then add API to our void* containers to box/unbox the data into GValue, or to specify the GType of the elements, without having to create a GTypeArray, a GTypePtrArray, or a GTypeHashTable inside libgobject.

Comments

I misspoke and should have said GType in my comment, not GObject, sorry.

The type system by itself isn’t a huge deal; it wouldn’t be problematic for people using only the GLib data structures.

I think it would be a bit of a deal if they were not using GType already, and then this change forced them to use, or integrate with, GType. We can design this so that doesn’t have to be the case, though.

Also, and to be quite blunt: it’s 2021. The objections on the basis of code size made sense 20 years ago, but just like the requirement to use modern toolchains,

I actually had more in mind the path dependency of projects which chose to use GLib (but not GObject) many years ago, and for whom changing to do anything else would be a lot of busy-work.

If we’re talking about best practice for projects in 2021, it would be to not use C at all, in the general case.

I find myself struggling to care about people using GLib like it’s 1997, and they only need a bunch of C data types.

Be nice.

We could then add API to our void* containers to box/unbox the data into GValue, or to specify the GType of the elements, without having to create a GTypeArray, a GTypePtrArray, or a GTypeHashTable inside libgobject.

A rough strawman of these APIs would be helpful.


I’d actually insist in keeping them isolated in libgobject, in case we decide to create a new base object class that does not have the known issues of GObject

… or just a better property or signal mechanism. I agree that this shouldn’t be in GLib in this form.


moving gtype.[ch] and gvalue.[ch] and ancillary private files from gobject to glib

How would that work with G_TYPE_OBJECT? Would that move as constant into GLib nonetheless?

And I assume interfaces would move to GLib completely together GTypeClass and GTypeInstance and all the corresponding machinery?


G_TYPE_OBJECT is just a fundamental type, so it can live inside libgobject, just like any other fundamental type inheriting from GTypeInstance does.

And I assume interfaces would move to GLib completely together GTypeClass and GTypeInstance and all the corresponding machinery?

Yes: GTypeClass, GTypeInstance, GTypeInterface, and GTypePlugin would move down one level. The latter is just an interface, so it does not have any further dependency, but the code inside GType checks for it when trying to gather type information.


Can we leave the plugin functionality behind ? I think that would be a nice win

We still need GTypePlugin around because it’s exposed in the GType API. The good news is that it’s just an interface, so it doesn’t do much by itself: you need to implement GTypeModule, which will automatically implement GTypePlugin. I don’t plan to move GTypeModule in libglib-2.0, mostly because it would require bringing GObject and GModule down one level.

1 Like

Just as a matter of reference, the only code that I maintain still that is GTypeModule-based is libpeas. It still uses it significantly as part of plugin loaders, as PeasObjectModule is a GTypeModule. That would definitely require ABI changes for me to ever be able to drop.

1 Like

It would be good to move GType and GValue down to glib so that types introduced in glib can define how they are stored in a GValue. I have effectively had to do this already to generate a static library of bindings using a hierarchical namespace. The problem in the bindings that Namespace.Type needs to know how to to store itself in a GValue but that can’t be done for GLib.Type because GValue isn’t available in GLib. The alternative approach of generating an extended version of GLib after the GObject namespace is available seemed even messier. With the flat namespace in C, there is no issue adding glib functions in gobject but that could be tidied up. (Presumably gboxed.[ch] would move down to glib too as that provides g_boxed_type_register_static which is referenced by a macro in gtype.h.)

This is being proposed for libglib-2.0. Wouldn’t that cause alias “Type” and record “Value” to change namespace from GObject to GLib? In the bindings that I have developed that would mean the structure GObject.Type would become GLib.Type which would break code like

        val list =
          Gtk.ListStore.new (
            GObjectTypeCArrayN.fromList [
              GObject.Type.int (),
              GObject.Type.string (),
              GObject.Type.string ()
            ]
          )

because e.g. GLib.Type.int () would be needed instead.

Also, I am surprised that the proposal is to add run-time type information to some GLib container types. Isn’t the deficiency that GType/GValue can’t provide the element type of a container type?

We can maintain compatibility aliases for introspection.