Gtk2::devel(3)

πŸ“¦
version 1.24993 Β· 2 versions
, in fedora 43

πŸ’– Gtk2::devel πŸ’–

okay bestie, so this is the Gtk2::devel page β€” it's a section 3 man page from the User Contributed Perl Documentation corner of the world, and it's the deep lore drop for the internal workings of the gtk2-perl language bindings. it's giving "backstage pass" energy fr. πŸŽ€


🌸 DESCRIPTION 🌸

okay so first thing: this doc is a supplement to Glib::devel, and it fully assumes you've already read and understood how the base Glib bindings work. like, genuinely. if you haven't, most of this is gonna read like nonsense and that's not a you problem, that's just how it is. πŸ’€

here's where we're at though: we're focusing on the ways Gtk2 extends Glib's concepts to bind the Gtk+ C libraries to perl β€” a whole methodology and set of tools you can use to wrap your very own GObject-based libraries. main character energy, honestly. πŸ‘‘


πŸ¦‹ GtkObject πŸ¦‹

so GtkObject adds the idea of a floating reference to GObject. here's the vibe check:

  • a GObject gets created with one reference, and that reference has to be explicitly removed by its owner. no take-backs, you own it.
  • a GtkObject has a floating reference, and that floating ref gets sunk by whatever code wants to own it. which makes creating a whole bunch of objects in a row way less painful β€” you don't have to unref them all one by one. slay. ✨

to allow for this difference in procedure for taking ownership of an object, Glib lets you register a "sink" function for a particular class. so when something asks to create a wrapper that owns the object, gperl_new_object compares the list of registered sink functions against the type of the object. if the object is descended from a type, that sink function runs on the object. the default one is g_object_unref(), of course. (this is inspired by pygtk.) 🫢

so like, in Gtk2::Object's boot code, we register gtk_object_sink as the sink func for types derived from GtkObject. and now every wrapper for those types gets owned the proper way. periodt.

and of course, since gtk_object_sink() does literally nothing if the object isn't floating, it doesn't hurt anything if you always call gperl_new_object with "own" set to TRUE. so to make life a little easier, Gtk2 defines another function:

 SV * gtk2perl_new_gtkobject (GtkObject * o);

which does nothing more than this:

{
    return gperl_new_object (G_OBJECT (o), TRUE);
}

also important to know: this is largely done for you by the typemap. 😌


🌈 Typemap scheme 🌈

in the same way the Glib module uses explicit one-to-one GType to package registrations, it's most foolproof to use an explicit, even exhaustive, XS typemap. this way we dodge all the problems β€” like finding the proper set of regexes to map $var to the type macro, and all sorts of other extensibility headaches. which of course means it must be autogenerated, but that's easy (and it's described in the next section). πŸ’…

the other main feature of the typemap is that it masks in a very sensible way the differences between GObject and GtkObject, and it makes it super easy to specify whether a wrapper owns the object it wraps. this is handled through the idea of a "variant" β€” which is a term I made up just now because it sounds about right. πŸ’€

basically, a variant is the name of the class with some suffix. for example, for a GBoxed subclass such as GdkEvent, a header would do this:

typedef GdkEvent GdkEvent_ornull;
typedef GdkEvent GdkEvent_own;

#define SvGdkEvent(s)           (gperl_get_boxed_check ((s), GDK_TYPE_EVENT))
#define SvGdkEvent_ornull(s)    ((s)==&PL_sv_undef ? NULL : SvGdkEvent(s))

#define newSVGdkEvent(e)        (gperl_new_boxed ((e), GDK_TYPE_EVENT, FALSE))
#define newSVGdkEvent_own(e)    (gperl_new_boxed ((e), GDK_TYPE_EVENT, TRUE))
#define newSVGdkEvent_ornull(e) (e == NULL ? &PL_sv_undef ? newSVGdkEvent (e))

then the typemap entries for its various variants would look like this:

TYPEMAP
GdkEvent *     T_GDK_TYPE_EVENT
GdkEvent_ornull *      T_GDK_TYPE_EVENT_ORNULL
GdkEvent_own * T_GDK_TYPE_EVENT_OWN

INPUT
T_GDK_TYPE_EVENT
       $var = SvGdkEvent ($arg);
T_GDK_TYPE_EVENT_ORNULL
       $var = SvGdkEvent_ornull ($arg);

OUTPUT
T_GDK_TYPE_EVENT
       $arg = newSVGdkEvent ($var);
T_GDK_TYPE_EVENT_ORNULL
       $arg = newSVGdkEvent_ornull ($var);
T_GDK_TYPE_EVENT_OWN
       $arg = newSVGdkEvent_own ($var);

and with all that in place, your XS wrapper code can look as simple as this:

GdkEvent_own *
gdk_get_event (class)
        SV * class
    C_ARGS:
        /*void*/

guint
gdk_event_get_time (event)
        GdkEvent * event

isn't that nice and simple?? πŸ₯Ή iconic.

we have different variants for different types, and some of them are applicable only to input or output. the ones used by gtk2-perl generally follow the convention outlined here β€” I means it applies to input, O means it applies to output:

GBoxed gang:

  • /* no ext */ β€” I βœ… O βœ… β€” the object will not be destroyed with the wrapper
  • _own β€” O βœ… only β€” the object will be destroyed with the wrapper
  • _copy β€” O βœ… only β€” the object will be copied (and the copy will be owned)
  • _ornull β€” I βœ… O βœ… β€” undef/NULL is legal
  • _own_ornull β€” O βœ… only β€” if the object is not NULL, the wrapper will own the object

GObject gang:

  • /* no ext */ β€” I βœ… O βœ… β€” the object's refcount will be increased (=> not owned)
  • _noinc β€” O βœ… only β€” the object's refcount will not be increased (=> owned)
  • _ornull β€” I βœ… O βœ… β€” undef/NULL is legal

GtkObject gang:

  • /* no ext */ β€” I βœ… O βœ… β€” everything is peachy
  • _ornull β€” I βœ… O βœ… β€” undef/NULL is legal

✨ Autogeneration ✨

the typemap scheme described above is great and all, but it involves creating a lot of typedefs and macros. for a large library like Gtk, with over three hundred types to bind, you'd have to be genuinely unwell to write all of those by hand. 😭

Gtk2 handles this by using a code generation module to write the code for us as part of the Makefile.PL configuration step. see Gtk2::CodeGen for details on how to use the generators. here I'll describe what gets generated and why. 🧚

πŸŽ€ maps πŸŽ€

this is the starting point for autogeneration β€” the input for the code generator. this map lists the TYPE macro for each of the GObject types in all of the gtk headers (including gdk, gdk-pixbuf, atk, and pango), along with:

  • the actual name of the class
  • the name of the package into which it is to be blessed
  • the base type (not exactly the fundamental type)

most of those should be obvious except for the base type. the base type is one of GEnum, GFlags, GBoxed, GObject, GInterface, or GtkObject. this is the important flag which determines what kind of code gets created for each record β€” GObjects must be handled by completely different code than GBoxed objects, for instance. as noted elsewhere, the distinction between GObject and GtkObject is not strictly necessary, but it's kept for historical and aesthetic reasons. πŸ’…

in this file, you can change the explicit name of an object. if you don't like PangoFontDescription being Gtk2::Pango::FontDescription, you can change it to Gtk2::Pango::Font::Desc::ription if you were so inclined (but please don't). πŸ™ˆ

if you wish to use Gtk2's autogeneration tools in your own project, you'll need to create a maps file. this can be done by hand, but that's tedious and error-prone; I used a script (called genmaps.pl in CVS) that actually scans the gtk header files and creates and runs a small program to generate the maps file. the advantage here is that the type information comes directly from the code and I don't have to worry about clerical errors making the software incorrect. in practice, this should need to be run only when new classes are added to the base libraries.

🧁 gtk2perl-autogen.h 🧁

this file contains the generated typedefs and cast macros. this includes all the variant stuff described above. ✨

πŸ“ gtk2perl.typemap πŸ“

the exhaustive typemap uses the macros defined in gtk2perl-autogen.h so that you are assured to get the same results from typemap generated code as from hand-written perl stack manipulation. no cap.

πŸ’œ register.xsh πŸ’œ

included from the BOOT section of the toplevel Gtk2 module (xs/Gtk2.xs), this file lists all of the types in the maps file as a series of calls to the appropriate package registration functions (gperl_register_boxed, gperl_register_object, or gperl_register_fundamental). this is done before the boot code below so that hand-written code may override it. this code gets executed when your perl script does a use Gtk2. πŸ”₯

🌸 boot.xsh 🌸

the Gtk2 module is made up of dozens of XS files but only one PM file. Gtk2.pm calls bootstrap on Gtk2, but not on any of the others (because it doesn't know about them). it is a module's boot code which binds the xsubs into perl, so it's imperative that the modules get booted!! 😀

so, Gtk2::CodeGen->write_boot (called from Makefile.PL) scans the xs/ subdirectory for all the MODULE = ... lines in the XS files. it maps these to boot code symbols, and generates code to call these symbols in boot.xsh, which is then included by the BOOT: section for the toplevel module, right after register.xsh. (the generation code takes steps to avoid spitting out the same symbol more than once, and will not emit code to boot the toplevel module β€” or else you get an infinite loop.) πŸ’€

just a point of style: you can change packages in an XS file by repeating the MODULE = ... line with a different PACKAGE (and possibly PREFIX) value. it's a good idea, however, to keep the MODULE the same, so that only one boot symbol gets generated per file. πŸ’…


πŸ‘‘ SEE ALSO πŸ‘‘


🫢 AUTHOR 🫢

muppet <scott at asofyet dot org>


Copyright (C) 2003 by the gtk2-perl team (see the file AUTHORS for the full list)

this library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

this library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. see the GNU Library General Public License for more details.

you should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


and that's the whole page bestie!! this one came to you courtesy of perl v5.42.0, dated 2025-07-25, filed under Gtk2::devel(3). go forth and wrap some GObjects, you absolute legend. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from