PLGI is a Prolog module that provides bindings to the entire GNOME software platform. GObject Introspection is used to dynamically generate Prolog predicates for C functions at runtime.

Perhaps the most notable use for PLGI is to write Gtk+ applications in Prolog. The full Gtk+ widget set is supported, along with other useful features such as drag-and-drop, clipboard management, internationalized text etc. PLGI also supports Glade UI files.

A number of short example programs exist in the plgi/examples directory highlighting some of the capabilities of PLGI.

Installation

PLGI has the following requirements:

SWI-Prolog >= 7.3.3 [1]

GLib-2.0 [2]

GObject Introspection >= 1.40 [3]

pkg-config [4]
The easiest way to install PLGI is by using SWI-Prolog's package manager:

?- pack_install(plgi).

PLGI can also be compiled and installed directly from sources in the following manner:

PLGI Namespaces

PLGI predicates are generated at runtime by loading GObject Introspection typelib files. Each typelib file is specified by it's namespace. Common namespaces include 'Gtk', 'Gdk', 'GObject', 'GLib' etc. Namespaces are loaded in the following manner:

plgi_use_namespace(+Namespace)

plgi_use_namespace('Gtk')

After loading a namespace, all functions, methods, objects, signals, structs, unions, enumerations and bitfields defined in that namespace are accessible from Prolog.

Loading a namespace will cause all its dependency namespaces to also be loaded. e.g. loading the 'Gtk' namespace will cause the lower-level 'Gdk' namespace to be loaded. Thus when writing GTK+ applications it is usually sufficient to include a single call to plgi_use_namespace('Gtk').

If typelib files exist in non-standard directories, they can be accessed in the following manner:

Many C functions that take array arguments also require an explicit array_length argument. The corresponding Prolog predicate does not specify a list length argument; The PLGI layer will automatically work this out. For example:

Arguments that have an (inout) annotation are represented in Prolog by two arguments - one for the (in) component and one for the (out) component.

C:
// 'position' points to location text will be inserted at
gint position = ...;
...
gtk_editable_insert_text(editable, text, text_length, &position);
// 'position' has been updated by gtk_editable_insert_text()
// to point after inserted text

GError arguments in C functions do not have corresponding Prolog arguments in the respective Prolog predicates. Similarly, GError return types will not be represented as Prolog arguments. A non-NULL GError argument in a C function will raise an exception in the corresponding Prolog predicate. For example:

Note #2: zero-terminated C arrays are represented in Prolog without their zero-terminated field. For example:

C:
gchar *values[] = { "foo", "bar", "baz", NULL };

Prolog:
Values = ['foo', 'bar', 'baz']

GObject Types

GObject types are represented in Prolog as opaque blobs.

GObject types do not need to be explicitly ref-bumped (or ref-sinked) when created or accessed, and do not need to be unrefed when no longer needed. The PLGI layer will automatically manage reference counting for GObject types. This often makes dealing with GObject types a bit less unwieldly in Prolog than in C:

This predicate is a wrapper around g_object_newv() but automatically translates Prolog property values into GValue+GParameter args. This predicate is of use if a C constructor is not introspectable, or GObject properties can only be set from a constructor. For example:

PLGI Limitations

There are a number of limitations with PLGI. While these limitations are not significant and do not prevent useful GTK+ code from being written, they are worth keeping in mind:

No custom GObject classes
It is currently not possible to define and create new GObject classes from Prolog. Only those classes defined in existing namespaces may be used. It is however still possible to override the behaviour of existing classes by defining local predicates. For example:

Not all GTK+ C functions are available
Only those functions and methods defined in GObject Introspection typelib files are available from Prolog. There are a number of C functions that are unavailable from Prolog as they have been defined using C #define directives or have been explicitly marked as not introspectable. Other notable C functions unavailable from Prolog include varargs functions. However, it should be noted that most varargs functions include variants which can be called from Prolog. e.g. gtk_dialog_add_buttons() is not available but calling gtk_dialog_add_button/4 multiple times is possible.

Structs with void* fields can leak memory
Arbitrary Prolog terms can be stored in a void* struct field using plgi_struct_new/2 or plgi_struct_set_field/3. If this struct becomes unused by the Gtk internals and goes out of scope in Prolog, then the struct will be freed from memory but the void* field data will not. If the struct has a short-lived lifetime, then it is recommended to manage this sort of term data in Prolog rather than using void* struct fields

GTK+ constants are not supported
Future PLGI work will include the addition of a helper predicate to convert a GTK+ constant name into its constant value.