Maybe it’s a a lot of detail if you aren’t used to GObject type system, but here it goes anyway:
I’m writing a binding generator for GObject based libraries and for GTK4 itself, GObject has properties, nowadays you can create a Crystal object that inherits a GObject and use an annotation to let it register this property on GObject.
class Foo < GObject::Object
property my_prop : Int32 = 0
You can pass the object above to a C function call and it will recognize the
How it works
In GObject C world this is done at type registration time (
class_init functions), in the bindings when a type is registered in the GObject type system a class method named
_class_init is called and scan the object instance variables with the
Property annotation to do the right C function calls to register the properties in the object.
So far so good, but in GTK there’s a function named
gtk_widget_class_add_binding_action, this function adds a gtk_widget_class_install_property_action that creates a GTK action for a GObject property, so when the action is triggered in the application the property value changes.
The problem is that this C function also needs to be called in the
_class_init function, it’s in another shard and the worst… I would like to implement this as a parameter anotation in the same
Property annotation, but this extra parameter would be handled by the GTK4 shard, not by the gi-crystal shard that has the GLib and GObject bindings.
I wanted this code:
# GObject::Object is part of Gtk::Widget hierarchy
class Foo < Gtk::Widget
property bar : Int32 = 0
# generated by an inherited macro on GObject::Object
# register the property, code created by a macro in GObject
# generated by an inherited macro on Gtk::Widget
GObject::Object uses a lot the
previous_def to create a chain of
_class_init function calls, because different features of GObject library need to call functions at class initialization time (a.k.a. class_init).
For example, when people do:
class Bar < Gtk::Widget
this also creates a
_class_init implementation telling GObject type system that this types implements this module, such implementation have a
previous_def call, so all
_class_init are called in the case of a type implement multiple interface or simple has multiple properties. The same for GObject virtual functions implementation in the bindings.
If everything gets implemented in GObject::Object all works, but I’ll be messing up hard with shard boundaries and this isn’t an option.
Anyway, seems a nice problem to solve.