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:
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 : ('a class, unit, unit, unit, unit) 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