@node The GLib type system, Gtk+ Gdk Pango Atk, Top, Top
@chapter The GLib type system

One key part of GLib is @code{libgobject}, an implementation of a
runtime, dynamic type system for C. Besides providing an object system
to C, its main design goal was to increase the ease with which C code
can be wrapped by interpreted languages, such as Guile or Perl.

Guile's wrapper is implemented by the module @code{(gnome gobject)}.
Go ahead and open up a Guile session and load it up:

@lisp
guile> (use-modules (gnome gobject))
@end lisp

We will leave off the @code{guile>} prompt in the rest of this
tutorial. When we want to show the value of an expression, we use
@result{}:

@lisp
(+ 3 5)
@result{} 8
@end lisp

Make some coffee, and let's dig in.

@menu
* Basic types::                 
* Enums and flags::             
* Closures::                    
* GType::                       
* GObject::                     
* Deriving your own GObject types::  
@end menu

@node Basic types, Enums and flags, The GLib type system, The GLib type system
@section Basic types

When communicating with @code{libgobject}, most values need to be
strictly-typed. There is a type class corresponding to each basic type
in C: @code{<gchar>}, @code{<guchar>}, @code{<gboolean>},
@code{<gint>}, @code{<guint>}, @code{<glong>}, @code{<gulong>},
@code{<gint64>}, @code{<guint64>}, @code{<gfloat>}, @code{<gdouble>},
and @code{<gchararray>}.

You can make instances of these class with @code{make}:

@lisp
(make <gboolean> #:value #f)
@result{} #<gvalue <gboolean> 40529040 #f>

(make <guint> #:value 85)
@result{} #<gvalue <guint> 4054f040 85>

(make <gfloat> #:value 3.1415)
@result{} #<gvalue <gfloat> 40556af0 3.1414999961853>

(make <gchararray> #:value "Hello World!")
@result{} #<gvalue <gchararray> 4055af90 Hello World!>
@end lisp

You can get the normal Scheme values back with @code{gvalue->scm}:

@lisp
(gvalue->scm (make <gchararray> #:value "Hello World!"))
@result{} "Hello World!"
@end lisp

@node Enums and flags, Closures, Basic types, The GLib type system
@section Enums and flags

Enumerated values and bitflags are an essential part of many C APIs, and so
they are specially wrapped in the GLib type system. You can create new
enumerated types in Scheme by subclassing @code{<genum>}:

@lisp
(define-class <foo> (<genum>)
  #:vtable '#((hello "Hello World" 1) (test "Test" 2)))
@end lisp

Instances are created with @code{make}, just like with the other
types:

@lisp
(make <foo> #:value 'hello)
(make <foo> #:value "Hello World")
(make <foo> #:value 1)

;; These three all do the same thing
@result{} #<gvalue <foo> 406275f8 (hello Hello World 1)>
@end lisp

If there's an already existing enum or flags class, you can get
information about it:

@lisp
(genum-class->value-table <foo>)
@result{} #((hello "Hello World" 1) (test "Test" 2))
@end lisp

Enums and flags have a special representation on the Scheme side. You
can convert them to Scheme values as symbols, names, or as a numeric
value.

@lisp
(define foo (make <foo> #:value 'hello))
(genum->symbol foo)
@result{} hello
(genum->name foo)
@result{} "Hello World"
(genum->value foo)
@result{} 1
@end lisp

@node Closures, GType, Enums and flags, The GLib type system
@section Closures

Another data type provided by @code{libgobject} is the closure, an
abstraction for callable objects. The actual object is a function in
some language, be it C, Scheme, or even Python. You can create a
closure in Guile with @code{make} (again):

@lisp
(define (times-eight x)
  (* x 8))

(define closure (make <gclosure> #:return-type <gint>
                  #:param-types (list <gulong>)
                  #:func times-eight))

(gclosure-invoke closure 10)
@result{} 80
@end lisp

The closure you create can then be passed to a C function, so that any
C function (even those that know nothing about Guile) can call back
into Scheme.

@node GType, GObject, Closures, The GLib type system
@section GType

All of the types that GLib knows about are available to Guile,
regardless of which language defined them. GLib implements this via a
type system, where every type has a name. So if you make a type called
``Foo'' in C, you can get to it in Scheme via @code{gtype-from-name}
and @code{gtype->class}:

@lisp
;; Retrieve the type for the foo enum we made earlier in the tutorial
(define foo-type (gtype-from-name "Foo"))
(define <foo> (gtype->class foo-type))

(make <foo> #:value 2)
@result{} #<gvalue <foo> 40535e50 (test Test 2)>
@end lisp

@node GObject, Deriving your own GObject types, GType, The GLib type system
@section GObject

@code{<gobject>} (@code{GObject} in C) is the basic object type in
@code{libgobject}. @code{(gnome gobject)} allows you to access
existing GObject types, as well as to create new GObject types in
Scheme.

Before we start, let's pull in some generic functions that reduce the
amount of typing we have to do:

@lisp
(use-modules (gnome gobject generics))
@end lisp

Let's assume we start with @code{<gtk-window>} from @code{(gnome gtk)}.
The keyword arguments to @code{make} are interpreted as GObject
properties to set:

@lisp
(define window (make <gtk-window>
                 #:type 'toplevel #:title "Hello, World!"))
@end lisp

You can connect to signals on the new instance:

@lisp
(connect window 'delete-event
         (lambda (window event)
           ;; Returns #t to ignore this event
           #t))

;; connect is a generic function implemented by
;; gtype-instance-signal-connect
@end lisp

And get and set properties...

@lisp
(get window 'title)
@result{} "Hello, World!"
(set window 'resizable #f)

;; get and set are also generics, implemented by gobject-get-property
;; and gobject-set-property
@end lisp

@node Deriving your own GObject types,  , GObject, The GLib type system
@section Deriving your own GObject types

You can create new GObject types directly from Scheme, deriving either
from a C object type or one you made in Scheme. Properties and signals
for the class, if any, should be set when you derive the class, not
afterwards.

@lisp
;; deriving from <gobject>
(define-class <test> (<gobject>)
  ;; a normal object slot
  my-data

  ;; an object slot exported as a gobject property
  (pub-data #:param-spec (list <gparam-long> #:name 'test))

  ;; a signal with no arguments and no return value
  #:signal '(frobate #f))

;; deriving from <test> -- also inherits properties and signals
(define-class <hungry> (<test>))
@end lisp

Adding a signal automatically defines the default method:

@lisp
;; This is the default handler for this signal.
(define-method (test:frobate (object <test>))
  (format #t "Frobating ~A\n" object))

;; We can override it for subclasses
(define-method (test:frobate (object <hungry>))
  (next-method) ;; chain up
  (format #t "I'm hungry\n"))

(emit (make <hungry>) 'frobate)
;; Try it!
@end lisp

You can override the @code{initialize}, @code{gobject:get-property},
and @code{gobject:set-property} methods. For an extended example, see
@code{tic-tac-toe.scm} in the @code{examples/gtk} directory of the
distribution.
