introspection.md 6.3 KB

how to use that Object Introspection in GTK4

If by “Object Introspection” you mean GTK4’s GObject introspection (GObject-Introspection / GI), it lets you use GTK4 from languages other than C by exposing GTK/GObject APIs through metadata.

The important distinction is:

GObject = GTK's object system.

GObject Introspection (GI) = metadata describing those GObjects, functions, methods, properties, signals, enums, etc.

GTK4 = built on top of GObject.

For example, from a language with GI support, you can introspect Gtk.Window and discover its methods and properties at runtime.

  1. Install the introspection data

On Debian/Ubuntu:

sudo apt install libgtk-4-dev gobject-introspection libgirepository1.0-dev

The GTK4 introspection data is normally installed as:

/usr/share/gir-1.0/Gtk-4.0.gir

You can inspect it:

less /usr/share/gir-1.0/Gtk-4.0.gir

You will see descriptions of things such as:

<class name="Window"

   parent="Gtk.Widget"
   type-name="GtkWindow"
   get-type="gtk_window_get_type">
...

  1. Using GI from a language

For example, Python uses PyGObject:

import gi

gi.require_version("Gtk", "4.0") from gi.repository import Gtk

Then:

window = Gtk.Window()

print(window.get_title())

And you can inspect the GObject dynamically:

print(type(window)) print(window.list_properties())

For example, you can enumerate the properties:

for prop in window.list_properties():

print(prop.name, prop.value_type.name)

You can also inspect signals and other GObject information.

  1. The really interesting part: GObject itself

Every GTK object ultimately participates in the GObject type system.

You can obtain the GType:

gtype = window.gtype print(gtype)

Conceptually, the hierarchy looks like:

GObject │ └── Gtk.Widget

      │
      └── Gtk.Window

The type system knows that Gtk.Window is a GObject type and contains information about its properties, signals, interfaces, parent type, etc.

  1. If you're interested in this for your Modula-2 compiler

This is actually quite interesting for your project, because GI can be treated almost like an external object/type database.

For example, you could potentially generate Modula-2 declarations from:

Gtk-4.0.gir

producing something conceptually like:

TYPE Window = POINTER TO WindowDesc;

WindowDesc = RECORD

...

END;

PROCEDURE WindowNew() : Window; PROCEDURE WindowSetTitle(w : Window; title : ADDRESS); PROCEDURE WindowPresent(w : Window);

And, with your OOP Modula-2 compiler, you could go considerably further and map GObject's type hierarchy to your own CLASS mechanism.

The interesting question then becomes whether you want to use GI merely as a binding generator, or implement a runtime introspection mechanism in Modula-2 itself.

If that's what you're aiming at, I can show you a concrete GTK4 + GObject Introspection → Modula-2 binding generator, including how to parse Gtk-4.0.gir and generate .def/.mod files.

C'est fait. J'ai préparé un prototype GIR → GNU Modula-2 que tu peux tester directement.

Télécharger m2gtk4-gir-generator.zip Ce que contient l'archive

m2gtk4gen/ ├── gir2m2.py ├── README.md └── examples/

├── Gtk-minimal.def
└── test.mod

Le générateur s'utilise ainsi :

python3 gir2m2.py /usr/share/gir-1.0/Gtk-4.0.gir -o gtk4

et produit :

gtk4/ └── Gtk.def

Exemple de résultat

Pour une classe GTK comme GtkWindow, on vise une représentation de ce genre :

DEFINITION MODULE FOR "C" Gtk ;

FROM SYSTEM IMPORT ADDRESS ;

EXPORT UNQUALIFIED GtkWindow,

               gtk_window_new,
               gtk_window_set_title,
               gtk_window_present,
               gtk_window_destroy ;

TYPE GtkWindowDesc = RECORD END ; GtkWindow = POINTER TO GtkWindowDesc ;

PROCEDURE gtk_window_new () : GtkWindow ; PROCEDURE gtk_window_set_title (self: GtkWindow; title: ARRAY OF CHAR) ; PROCEDURE gtk_window_present (self: GtkWindow) ; PROCEDURE gtk_window_destroy (self: GtkWindow) ;

END Gtk.

C'est basé sur le mécanisme DEFINITION MODULE FOR "C" de GNU Modula-2, qui est précisément prévu pour interfacer directement les fonctions C.

Et ARRAY OF CHAR est volontaire ici pour les paramètres utf8 : GNU Modula-2 le convertit en char * dans une définition de module C. Mais il reste une étape importante

Ce générateur est volontairement conservateur. Il ne prétend pas encore générer correctement toute GTK4. En particulier :

callbacks / function pointers

GValue

GError

GList / GSList

structures C

unions

tableaux GI complexes

transfer-full, transfer-none, etc.

propriétés GObject

signaux

interfaces

héritage GObject

GType

introspection dynamique via GIRepository

Et c'est justement là que ça devient intéressant pour ton compilateur Modula-2 avec OOP.

GTK4 possède une hiérarchie GObject réelle — par exemple Gtk.Window dérive de Gtk.Widget, lui-même de GInitiallyUnowned — que l'on peut récupérer depuis les données d'introspection.

L'étape suivante que je te conseille est donc de faire un vrai binding objet, plutôt que de simplement traduire les fonctions C :

             GObject
                │
         GInitiallyUnowned
                │
            GtkWidget
                │
            GtkWindow
             /      \
    GtkDialog     GtkApplicationWindow

et de produire dans ton dialecte quelque chose comme :

CLASS GtkWidget;

PROCEDURE Show(); PROCEDURE Hide(); PROCEDURE SetVisible(v: BOOLEAN);

END GtkWidget;

CLASS GtkWindow EXTENDS GtkWidget;

PROCEDURE SetTitle(title: ARRAY OF CHAR); PROCEDURE Present(); PROCEDURE Close();

END GtkWindow;

Tout en conservant l'ABI GObject réel derrière ces classes.

C'est à mon avis beaucoup plus intéressant pour ton compilateur que de reproduire simplement les .h GTK4 : GIR devient alors la source de description de l'API, et ton compilateur fait la traduction vers son propre système OOP. GTK documente d'ailleurs explicitement GObject comme son système objet et GI comme le mécanisme permettant de rendre les données d'introspection disponibles aux bindings.

Si tu veux aller dans cette direction, je peux faire la version 2 : GIR → classes OOP de ton Modula-2, avec GtkWidget, GtkWindow, propriétés et signaux GObject.