|
|
@@ -0,0 +1,230 @@
|
|
|
+ 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">
|
|
|
+ ...
|
|
|
+</class>
|
|
|
+
|
|
|
+2. 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.
|
|
|
+3. 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.
|
|
|
+4. 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.
|