Library Structure

The SML interface is organized using SML modules. The structure and content is inherited from the GObject Introspection (GI) metadata from which Giraffe Library is automatically generated, so would be similar to other GI-based libraries. The main exception to this are those areas relating to the GObject foundations — in particular, the structures GObjectType, GObjectValue, GObjectClosure — which are specific to Giraffe Library. These structures rarely need to be referenced by applications because the special structures provide higher-level type safe interfaces, in particular, for working with signals and properties.

Libraries

For each library, introspection provides one or more namespaces.

For example,

  • the library GLib provides the namespaces GLib, GObject, Gio, GModule;

  • the library Pango provides the namespace Pango;

  • the library GTK provides the namespaces Gdk and Gtk;

For each namespace Namespace, there is a signature NAMESPACE and a structure Namespace that implements the signature:

structure Namespace : NAMESPACE

For example:

structure GLib : G_LIB
structure GObject : G_OBJECT
structure Gio : GIO
structure GModule : G_MODULE

structure Pango : PANGO

structure Gdk : GDK
structure Gtk : GTK

Namespaces

A namespace may define the following entities:

  • named type (class, interface, record, union, enum, flags, callback or alias)

  • constant — see section Constants

  • function — see section Functions

The signature NAMESPACE contains a specification for each entity. The specification for a function and a constant is described in the sections referenced above.

For example:

signature GTK =
  sig
    (* named types *)
    …
    structure Button : GTK_BUTTON
    structure Window : GTK_WINDOW
    structure WindowGroup : GTK_WINDOW_GROUP
    structure WindowType : GTK_WINDOW_TYPE
    …

    (* constants *)
    val MAJOR_VERSION : LargeInt.int
    val MICRO_VERSION : LargeInt.int
    val MINOR_VERSION : LargeInt.int
    val STOCK_CANCEL : string
    …

    (* functions *)
    val init : string list -> string list
    val main : unit -> unit
    …
  end

For each named type Type in Namespace, the signature NAMESPACE contains a specification of a structure Type where a separate signature NAMESPACE_TYPE specifies the SML interface:

signature NAMESPACE =
  sig
    …
    structure Type : NAMESPACE_TYPE
    …
  end

Therefore, the SML interface of Namespace.Type is specified by NAMESPACE_TYPE.

For example GTK_WINDOW specifies the SML interface for Window:

    structure Window : GTK_WINDOW

Therefore, the SML interface of Gtk.Window is specified by GTK_WINDOW.

A named type may depend on other named types. Consequently, the signature for a named type typically refers to the SML type of other named types. A named type in another namespace can be referenced, e.g. Gdk.Rectangle.t, but a named type in the same namespace does not yet have a structure that implements it. Therefore local SML types are introduced in the signature that are linked in the namespace signature. This is not shown in the simplified example above.

For example, in the namespace Gtk, the class Window refers to the enum WindowType. Therefore the signature GTK_WINDOW needs to refer to WindowType.t but instead uses a local type window_type_t that is linked by the structure specification for Window as follows:

    structure Window :
      GTK_WINDOW
        where type 'a buildable_class = 'a Buildable.class
        where type 'a window_group_class = 'a WindowGroup.class
        where type 'a accel_group_class = 'a AccelGroup.class
        where type 'a application_class = 'a Application.class
        where type 'a widget_class = 'a Widget.class
        where type window_type_t = WindowType.t
        where type window_position_t = WindowPosition.t

Not only can a named type depend on another named type, two named types can be mutually dependent. In this case, there is no possible ordering of the structure specifications that satisfies the depencies.

For example, in the namespace Gtk, the class Window and class WindowGroup depend on each other's named type. The structure specification for WindowGroup would be as follows:

    structure WindowGroup :
      GTK_WINDOW_GROUP
        where type 'a widget_class = 'a Widget.class
        where type 'a window_class = 'a Window.class

This depends on the structure specification of Window but the structure specification of Window depends on this.

A cyclic dependency between structure specifications is avoided by introducing a separate structure that defines the SML type and no other part of the interface.

For example, for the class Window and class WindowGroup, the SML types are introduced by the structures WindowClass and WindowGroupClass, respectively. This avoids a cyclic dependency between the structure specifcations of Window and WindowGroup:

    structure WindowGroupClass : GTK_WINDOW_GROUP_CLASS
    …
    structure WindowClass :
      GTK_WINDOW_CLASS
        where type 'a bin_class = 'a BinClass.class
    …
    structure Window :
      GTK_WINDOW
        where type 'a class = 'a WindowClass.class
        where type 'a buildable_class = 'a BuildableClass.class
        where type 'a window_group_class = 'a WindowGroupClass.class
        where type 'a accel_group_class = 'a AccelGroupClass.class
        where type 'a application_class = 'a ApplicationClass.class
        where type 'a widget_class = 'a WidgetClass.class
        where type window_type_t = WindowType.t
        where type window_position_t = WindowPosition.t
    …
    structure WindowGroup :
      GTK_WINDOW_GROUP
        where type 'a class = 'a WindowGroupClass.class
        where type 'a widget_class = 'a WidgetClass.class
        where type 'a window_class = 'a WindowClass.class

Named types

A named type may define the following entities:

  • implemented interface (class and interface only) — see section Implemented interfaces

  • constant (class and interface only) — see section Constants

  • callable function (any named type except callback) — see section Functions — which may be a

    • method (class and interface only)

    • constructor (class and interface only)

    • function

  • virtual method (class and interface only) — unsupported, see section Giraffe Limitations

  • field (class, record and union only) — see section Fields

  • signal (class and interface only) — see section Signals

  • property (class and interface only) — see section Properties

  • member (enum and flags only)

The signature NAMESPACE_TYPE for the named type always specifies a type t as described in the section Types and contains a specification for each entity as described in the sections referenced above.

For example:

signature GTK_BUTTON =
  sig
    (* local types *)
    type 'a actionable_class
    type 'a activatable_class
    type 'a widget_class
    type position_type_t
    …

    (* type *)
    type 'a class
    type t = base class

    (* implemented interfaces *)
    val asActionable : 'a class -> base actionable_class
    val asActivatable : 'a class -> base activatable_class

    (* constructors *)
    val new : unit -> base class
    val newFromStock : string -> base class
    …

    (* methods *)
    val getLabel : 'a class -> string
    val setLabel : 'a class -> string -> unit
    …

    (* signals *)
    val clickedSig : (unit -> unit) -> 'a class Signal.t
    …

    (* properties *)
    val labelProp : ('a class, unit -> string option, string option -> unit, string option -> unit) Property.t
    …
  end

A callback has none of the entities listed above. Therefore, the signature for the callback specifies only the type t.

An alias is a named type defined in terms of another (named or unnamed) type. The signature for the alias is defined to be equal to the signature for the other type.

For example:

signature GTK_ALLOCATION_RECORD = GDK_RECTANGLE_RECORD