doc: documented the new GBoxed type mapping
authorDmitry Kalyanov <Kalyanov.Dmitry@gmail.com>
Sat, 8 Aug 2009 18:07:17 +0000 (22:07 +0400)
committerDmitry Kalyanov <Kalyanov.Dmitry@gmail.com>
Sat, 8 Aug 2009 18:07:17 +0000 (22:07 +0400)
doc/gobject.texi

index 9a5fb03..be0ff1b 100644 (file)
@@ -194,8 +194,8 @@ Some of the types are fundamental and have constant integer values. They are ide
 @item @code{+g-type-double+} ("gdouble"). The fundamental type corresponding to @code{gdouble}.
 @item @code{+g-type-string+} ("gchararray"). The fundamental type corresponding to null-terminated C strings.
 @item @code{+g-type-pointer+} ("gpointer"). The fundamental type corresponding to @code{gpointer}.
-@item @code{+g-type-boxed+} ("GBoxed"). The fundamental type from which all boxed types are derived.
-@item @code{+g-type-param+} ("GParam"). The fundamental type from which all GParamSpec types are derived.
+@item @code{+g-type-boxed+} ("GBoxed"). The fundamental type from which all boxed types are derived. Values of this type correspond to by-value structures.
+@item @code{+g-type-param+} ("GParam"). The fundamental type from which all GParamSpec types are derived. Values of this type correspond to instances of structure @code{g-class-property-definition}.
 @item @code{+g-type-object+} ("GObject"). The fundamental type for GObject.
 @end itemize
 
@@ -1679,33 +1679,47 @@ Example:
   (:skip tree-model-rows-reordered :pointer)
   ;;methods
   (tree-model-get-flags-impl tree-model-get-flags-cb
-    tree-model-flags (tree-model g-object))
+    tree-model-flags
+    (tree-model g-object))
   (tree-model-get-n-columns-impl tree-model-get-n-columns-cb
-    :int (tree-model g-object))
+    :int
+    (tree-model g-object))
   (tree-model-get-column-type-impl tree-model-get-column-type-cb
-    g-type (tree-model g-object) (index :int))
+    g-type-designator
+    (tree-model g-object) (index :int))
   (tree-model-get-iter-impl tree-model-get-iter-cb
-    :boolean (tree-model g-object) (iter (g-boxed-ref tree-iter)) (path (g-boxed-ref tree-path)))
+    :boolean
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)) (path (g-boxed-foreign tree-path)))
   (tree-model-get-path-impl tree-model-get-path-cb
-    (g-boxed-ref tree-path) (tree-model g-object) (iter (g-boxed-ref tree-iter)))
+    (g-boxed-foreign tree-path :return)
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)))
   (tree-model-get-value-impl tree-model-get-value-cb
-    :void (tree-model g-object) (iter (g-boxed-ref tree-iter)) (n :int) (value (:pointer g-value)))
+    :void
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)) (n :int) (value (:pointer g-value)))
   (tree-model-iter-next-impl tree-model-iter-next-cb
-    :boolean (tree-model g-object) (iter (g-boxed-ref tree-iter)))
+    :boolean
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)))
   (tree-model-iter-children-impl tree-model-iter-children-cb
-    :boolean (tree-model g-object) (iter (g-boxed-ref tree-iter)) (parent (g-boxed-ref tree-iter)))
+    :boolean
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)) (parent (g-boxed-foreign tree-iter)))
   (tree-model-iter-has-child-impl tree-model-iter-has-child-cb
-    :boolean (tree-model g-object) (iter (g-boxed-ref tree-iter)))
+    :boolean
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)))
   (tree-model-iter-n-children-impl tree-model-iter-n-children-cb
-    :int (tree-model g-object) (iter (g-boxed-ref tree-iter)))
+    :int
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)))
   (tree-model-iter-nth-child-impl tree-model-iter-nth-child-cb
-    :boolean (tree-model g-object) (iter (g-boxed-ref tree-iter)) (parent (g-boxed-ref tree-iter)) (n :int))
+    :boolean
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)) (parent (g-boxed-foreign tree-iter)) (n :int))
   (tree-model-iter-parent-impl tree-model-iter-parent-cb
-    :boolean (tree-model g-object) (iter (g-boxed-ref tree-iter)) (child (g-boxed-ref tree-iter)))
+    :boolean
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)) (child (g-boxed-foreign tree-iter)))
   (tree-model-ref-node-impl tree-model-ref-node-cb
-    :void (tree-model g-object) (iter (g-boxed-ref tree-iter)))
+    :void
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter)))
   (tree-model-unref-node-impl tree-model-unref-node-cb
-    :void (tree-model g-object) (iter (g-boxed-ref tree-iter))))
+    :void
+    (tree-model g-object) (iter (g-boxed-foreign tree-iter))))
 @end lisp
 
 @node register-object-type-implementation
@@ -1742,8 +1756,13 @@ Example:
 @node GBoxed
 @chapter GBoxed
 @menu
-* define-g-boxed-class::
-* define-g-boxed-ref::
+* define-g-boxed-cstruct::
+* define-g-boxed-variant-cstruct::
+* define-g-boxed-opaque::
+* g-boxed-opaque::
+* define-boxed-opaque-accessor::
+* boxed-related-symbols::
+* GBoxed foreign type::
 @end menu
 
 GObject manual defines this type in the following way:
@@ -1752,251 +1771,343 @@ GObject manual defines this type in the following way:
 
 Boxed types are useful for simple value-holder structures like rectangles or points. They can also be used for wrapping structures defined in non-GObject based libraries.''
 
-Naturally, it is quite hard to provide support for such structures. At the moment, support for GBoxed is pretty bad.
-
-Basically, two use cases of GBoxed structures are provided:
+Naturally, it is hard to provide support for ``arbitrary C structures''. We support a few useful use cases of GBoxed types:
 @itemize
-@item structure is mapped to Lisp structure defined with @code{defstruct}. This is complex scenario and it supports inheritance between structure. Its main use is to define the @code{GdkEvent} structure wrapper. Macro @code{define-g-boxed-class} supports this use case.
-@item structure is mapped to Lisp wrapper that contains pointer to structure and provides accessor functions (by calling foreign function or calling Lisp function). Macro @code{define-g-boxed-ref} supports this use case.
+@item Simple C structures. A Lisp structure is a one-to-one correspondence to C structure and is passes to and from foreign code by copying the data it contains. Examples of simple structures are GdkPoint, GdkRectangle.
+@item ``Variant'' C structures. A one common idiom of C is to define a union of structures sharing the same parts in order to implement the polymorphism of structures. These structures are mapped to a hierarchy of Lisp structures (where one structure subclasses another via the @code{:include} @code{defstruct} option).
+
+For example, Gdk has structure GdkEvent which is a union of GdkEventAny, GdkEventExpose and other structures. These structures have common slots: ``type'', ``window'', ``send_event''. By dispatching on ``type'', user or GdkEvent structure knows which of GdkEvent* structures it has and can access other fields.
+@item Opaque C structures. A C structure the has ``hidden'' fields and should only created/destroyed with specific functions and be accessed only with specific accessors. Example of such structures is GtkTreePath.
 @end itemize
 
-In both scenarios, foreign functions and GValue type registrations are provided that provide wrapping and unwrapping behaivour (it yet remains to be proven that the behaviour is correct in all cases with regard to issues of memory management, ownership, lifetime). In both cases it is possible to pass the structure by reference, allowing the foreign function (or the callback code) to change the contents of GBoxed.
+@node define-g-boxed-cstruct
+@section define-g-boxed-cstruct
+@lisp
+(define-g-boxed-cstruct name g-type-name
+  &body slot*)
+
+slot ::= (slot-name slot-type &key count initform inline)
+@end lisp
+
+@table @var
+@item @var{name}
+A symbol naming the type being defined
+@item @var{g-type-name}
+A string specifying the GType name of this GBoxed. This may be nil if this type is not registered with GObject type system.
+@item @var{slot-name}
+A symbol naming the slot of a structure
+@item @var{slot-type}
+A foreign type of a slot
+@item @var{count}
+An integer. Corresponds to @code{:count} option of slot in CFFI @code{defcstruct}. If @code{count} is not NIL, then the slot is mapped to Lisp array.
+@item @var{initform}
+A form that is the initform of Lisp structure slot
+@item @var{inline}
+A boolean. If it is true, then the slot contains GBoxed structure whose name is @code{slot-type}.
+@end table
+
+Defines the ``simple'' GBoxed structure corresponding to C structure. The slot specification is analogous to CFFI @code{defstruct} slot specification with the addition of @code{inline} option.
+
+Example of usage:
+@lisp
+(define-g-boxed-cstruct rectangle "GdkRectangle"
+  (left :int :initform 0)
+  (top :int :initform 0)
+  (width :int :initform 0)
+  (height :int :initform 0))
 
-It is expected that the support for GBoxed structures will be improved.
+(define-g-boxed-cstruct point nil
+  (x :int :initform 0)
+  (y :int :initform 0))
 
-@node define-g-boxed-class
-@section define-g-boxed-class
+(define-g-boxed-cstruct vector4 nil
+  (coords :double :count 4 :initform (vector 0d0 0d0 0d0 0d0)))
+
+(define-g-boxed-cstruct segment nil
+  (a point :inline t :initform (make-point))
+  (b point :inline t :initform (make-point)))
+@end lisp
+
+@node define-g-boxed-variant-cstruct
+@section define-g-boxed-variant-cstruct
 
 @lisp
-(define-g-boxed-class g-name-and-c-name name (&optional superclass-and-dispatch (export t))
-  &body slot*)
+(define-g-boxed-variant-cstruct name g-type-name
+  &body slot-or-variant-specification*)
 
-g-name-and-c-name ::= nil
-g-name-and-c-name ::= (g-name c-name)
-superclass-and-dispatch ::= (&optional superclass dispatch-slot dispatch-values)
-slot ::= slot-name slot-type &key initform parser unparser
+slot ::= (slot-name slot-type &key count initform inline)
+variant-specification ::= (:variant dispatching-slot-name structure-variant*)
+structure-variant ::= (dispatching-slot-values structure-name &body slot-or-variant-specification*)
 @end lisp
 
 @table @var
-@item @var{g-name}
-A string naming the type of this GBoxed; for inherited classes, it should be @code{NIL}
-@item @var{c-name}
-A symbol naming the generated CFFI foreign structure definition corresponding to this GBoxed. This name should not conflict with other CFFI types.
 @item @var{name}
-A symbol naming the Lisp structure that will be generated
-@item @var{superclass}
-A symbol naming the structure defined with @code{define-g-boxed-class} that is the superclass of this structure
-@item @var{dispatch-slot}
-A slot of the superclass structure that identifies the specific type of structure (``discriminator'')
-@item @var{dispatch-values}
-A value or a list of values of the @code{dispatch-slot} that correspond to this GBoxed class
+A symbol naming the type being defined
+@item @var{g-type-name}
+A string specifying the GType name of this GBoxed. This may be nil if this type is not registered with GObject type system.
 @item @var{slot-name}
-Name of a slot
+A symbol naming the slot of a structure
 @item @var{slot-type}
-CFFI foreign type of a slot
+A foreign type of a slot
+@item @var{count}
+An integer. Corresponds to @code{:count} option of slot in CFFI @code{defcstruct}. If @code{count} is not NIL, then the slot is mapped to Lisp array.
 @item @var{initform}
-An optional initform for @code{defstruct} slot
-@item @var{parser}
-An optional parser function designator for slot. Parser function is called to get the value for slot when the GBoxed is passed to Lisp with the following arguments: @code{(name pointer)} where the @code{name} is the name of a structure being defined and the @code{pointer} is a foreign pointer to the C structure.
-@item @var{unparser}
-An optional unparser function designator for a slot. Unparser function is called to write the slot value to GBoxed structure. It is called with arguments @code{(name pointer object)} where @code{name} is the name of a structure being defined, @code{pointer} is the pointer to the C structure and the @code{object} is object whose slot value should be written to structure.
+A form that is the initform of Lisp structure slot
+@item @var{inline}
+A boolean. If it is true, then the slot contains GBoxed structure whose name is @code{slot-type}.
+@item @var{dispatching-slot-name}
+A name of the dispatching slot
+@item @var{dispatching-slot-values}
+A single value or a list of values.
+@item @var{structure-name}
+A symbol naming the structure
 @end table
 
-Defines the @code{defstruct} wrapper for GBoxed type. Various parameters control how the structure is converted between C and Lisp representations.
-
-@code{define-g-boxed-class} supports basic single inheritance. This is provided to support ``generic'' C structures like @code{GdkEvent} that contain a ``type'' field and a @code{union} of other substructures. The natural mapping of such structure to Lisp is not one, but several structures that are inherited one from another. This supports e.g. method dispatching on @code{GdkEvent} types (if it is ever necessary).
+Defines the variant GBoxed structure. Slots of variant structures are defined the same way as the slots of ``simple'' cstructs. After the last slot, @code{variant-specification} may be used to specify the variants of the structure. For this, dispatching slot is specified. The value of this slot specifies which variant of structure is used. Each variant is specified by values of the dispatching slot, by its slots and its variants.
+
+Variant structure is represented in Lisp via a hierarchy on structures. For example, @code{GdkEvent} structure has variants @code{GdkEventAny}, @code{GdkEventButton}, @code{GdkEventMotion}. In Lisp, @code{event} structure is defined with all common fields of these structures and @code{event-button}, @code{event-motion} structures inherit from @code{event} structure.
+
+It is assumed that the variant of structures can be represented as C structures with fields of their ``parent'' structures prepended to them. This assumption breaks when structures include their ``parent'' structure as a first field (this changes the memory alignment and changes offsets of fields).
+
+For example, for these structures this assumption holds:
+@example
+union GdkEvent
+@{
+  GdkEventType   type;
+  GdkEventKey    key;
+  GdkEventButton button;
+@};
+
+struct GdkEventKey @{
+  GdkEventType type; //
+  GdkWindow *window; // These fields are common
+  gint8 send_event;  //
+  guint32 time;
+  guint state;
+  guint keyval;
+  ...
+@};
+
+struct GdkEventButton @{
+  GdkEventType type; //
+  GdkWindow *window; // These fields are common
+  gint8 send_event;  //
+  guint32 time;
+  gdouble x;
+  gdouble y;
+  ...
+@};
+@end example
 
-The only use of @code{define-g-boxed-class} that involves inheritance is the @code{GdkEvent} structure. It is defined as follows.
+Example:
 @lisp
-(define-g-boxed-class ("GdkEvent" event-struct) event ()
+(define-g-boxed-variant-cstruct event "GdkEvent"
   (type event-type)
   (window (g-object gdk-window))
-  (send-event (:boolean :int8)))
-
-(define-g-boxed-class nil event-key ((event type (:key-press :key-release)))
-  (time :uint32)
-  (state modifier-type)
-  (keyval :uint)
-  (length :int)
-  (string (:string :free-from-foreign nil :free-to-foreign nil))
-  (hardware-keycode :uint16)
-  (group :uint8)
-  (is-modifier :uint))
-
-(define-g-boxed-class nil event-button ((event type (:button-press :2button-press :3button-press :button-release)))
-  (time :uint32)
-  (x :double)
-  (y :double)
-  (axes (fixed-array :double 2))
-  (state :uint)
-  (button :uint)
-  (device (g-object device))
-  (x-root :double)
-  (y-root :double))
+  (send-event (:boolean :int8))
+  (:variant type
+            ((:key-press :key-release) event-key
+             (time :uint32)
+             (state modifier-type)
+             (keyval :uint)
+             (length :int)
+             (string (:string :free-from-foreign nil
+                              :free-to-foreign nil))
+             (hardware-keycode :uint16)
+             (group :uint8)
+             (is-modifier :uint))
+            ((:button-press :2button-press :3button-press
+              :button-release) event-button
+             (time :uint32)
+             (x :double)
+             (y :double)
+             (axes (fixed-array :double 2))
+             (state :uint)
+             (button :uint)
+             (device (g-object device))
+             (x-root :double)
+             (y-root :double))
+             ...))
 @end lisp
 
-Some simpler uses include following examples:
+This code defines following structures:
 @lisp
-(define-g-boxed-class "GdkFont" font ()
-  (type font-type :initform :font)
-  (ascent :int :initform 0)
-  (descent :int :initform 0))
+(defstruct event
+  type window send-event)
 
-(define-g-boxed-class "GdkColor" color ()
-  (pixel :uint32 :initform 0)
-  (red :uint16 :initform 0)
-  (green :uint16 :initform 0)
-  (blue :uint16 :initform 0))
+(defstruct (event-key (:include event))
+  time state keyval length string
+  hardware-keycode group is-modifier)
 
-(define-g-boxed-class "GdkGeometry" geometry ()
-  (min-width :int :initform 0)
-  (min-height :int :initform 0)
-  (max-width :int :initform 0)
-  (max-height :int :initform 0)
-  (base-width :int :initform 0)
-  (base-height :int :initform 0)
-  (width-increment :int :initform 0)
-  (height-increment :int :initform 0)
-  (min-aspect :double :initform 0.0d0)
-  (max-aspect :double :initform 0.0d0)
-  (gravity gravity :initform :north-west))
+(defstruct (event-button (:include event))
+  time x y axes state button device x-root y-root)
 @end lisp
 
-@node define-g-boxed-ref
-@section define-g-boxed-ref
+@node define-g-boxed-opaque
+@section define-g-boxed-opaque
 
-@code{g-boxed-ref} class is defined:
 @lisp
-(defclass g-boxed-ref ()
-  ((pointer :accessor pointer :initarg :pointer)))
+(define-g-boxed-opaque name g-type-name &key alloc)
 @end lisp
 
-This class holds the pointer to structure. GBoxed-ref types are subclasses of this class.
+@table @var
+@item @var{name}
+A name of boxed type
+@item @var{g-type-name}
+A string; the name of GType
+@item @var{alloc}
+A form that when evaluated produces a pointer to newly allocated structure. This pointer should be copiable with @code{g_boxed_copy} and freeable with @code{g_boxed_free} function.
+@end table
+
+Defines a opaque boxed structure. A class named @var{name} is defined as a subclass of @code{g-boxed-opaque} class. Instances of this class contain pointers to corresponding structures. An @code{:after} method for @code{initialize-instance} generic function is defined that speciales on class @var{name}. This method either accepts a @code{:pointer} initarg or evaluates @var{alloc} form if @code{:pointer} is not specified; the resulting pointer is saved in instance; finalizer is registered to free the pointer when the garbage collectors deletes this object.
 
+Example:
 @lisp
-(define-g-boxed-ref g-name name
-  &rest property*)
+(defcfun gtk-tree-path-new :pointer)
 
-property ::= (:free-function free-function)
-property ::= (:alloc-function alloc-function)
-property ::= (:slots &rest slot*)
-slot ::= (slot-name &key reader writer type (accessor slot-name))
+(define-g-boxed-opaque tree-path "GtkTreePath"
+  :alloc (gtk-tree-path-new))
+@end lisp
+@node g-boxed-opaque
+@section g-boxed-opaque
+@lisp
+(defclass g-boxed-opaque ()
+  ((pointer :initarg :pointer
+            :initform nil
+            :accessor g-boxed-opaque-pointer)))
+@end lisp
+
+A class that is the base class for wrappers of opaque structures. Contains a pointer to the wrapped opaque structure.
+
+Accessor function @code{g-boxed-opaque-pointer} is used to access the pointer. Pointer should not be modified directly, only read.
+@node define-boxed-opaque-accessor
+@section define-boxed-opaque-accessor
+@lisp
+(define-boxed-opaque-accessor
+  boxed-name accessor-name &key type reader writer)
 @end lisp
 
 @table @var
-@item @var{g-name}
-A string that names the GBoxed type
-@item @var{name}
-A symbol that is the name for generated class
-@item @var{free-function}
-Mandatory designator for a function that frees the allocated object. This function accepts a single argument - CFFI foreign pointer.
-@item @var{alloc-function}
-Mandatory designator for a function that allocates the object. This function accepts zero arguments and returns CFFI foreign pointer to fresh object.
-@item @var{slot-name}
-A symbol naming the slot
+@item @var{boxed-name}
+A symbol naming the opaque structure type for which the accessor is being defined
+@item @var{accessor-name}
+A symbol naming the accessor
 @item @var{type}
-A CFFI foreign type of a slot
+A CFFI foreign type of the property for which the accessor is being defined
 @item @var{reader}
-@code{NIL} or a string or a function designator. If it is @code{NIL} the the slot is not readable. If it is a string then it names the C function that accepts the pointer to structure and returns the value of a slot of specified CFFI type. If it is a function designator that it designates a function that accepts the Lisp object and returns its slot value.
+A @code{NIL} or a string or a function designator for the reader function
 @item @var{writer}
-@code{NIL} or string or a function designator. If it is a @code{NIL} then the slot is not writable. If it is a string then it names the C function that accepts the pointer to C structure and a value (of specified CFFI type) and assigns it to the slot of a structure. If it is a function designator then it specifies a function that accepts the new slot value and a Lisp object and assigns it to the slot.
-@item @var{accessor}
-A symbol namin the accessor function for slot.
+A @code{NIL} or a string or a function designator for the writer function
 @end table
 
-Defines a class corresponding to GBoxed type that is passed by reference (e.g., @code{GtkTextIter}). Class is made a subclass of @code{g-boxed-ref}.
+Defines the accessor named @var{accessor-name} for property of opaque structure named @var{boxed-name} of type specified by CFFI foreign-type @var{type}.
 
-The memory occupied by this class is managed automatically: after the GC collects the Lisp instance, @code{free-function} is used to free the structure (if the instance was created by lisp code).
+@var{reader} is a string naming a foreign function of one argument of CFFI foreign-type @code{(g-boxed-foreign @var{boxed-name})} that returns a value of CFFI foreign-type @var{type}; or a function designator for a function that accepts a single argument - an instance of @code{g-boxed-opaque} class and returns the value of a property; or a @code{NIL} if the property is not readable.
+
+@var{writer} is a string naming a foreign function of two arguments: of types @var{type} and @code{(g-boxed-foreign @var{boxed-name})} (with the first argument being the new value and the second being the object); or a function designator for a function of two arguments: a new value and an instance of @code{g-boxed-opaque} class; or a @code{NIL} if the property is not writable.
+
+Example:
+@lisp
+(define-boxed-opaque-accessor text-iter text-iter-child-anchor
+  :reader "gtk_text_iter_get_child_anchor" :type (g-object text-child-anchor))
+
+(define-boxed-opaque-accessor text-iter text-iter-tags
+  :reader "gtk_text_iter_get_tags" :type (gslist (g-object text-tag) :free-from-foreign t))
+
+(define-boxed-opaque-accessor text-iter text-iter-chars-in-line
+  :reader "gtk_text_iter_get_chars_in_line" :type :int)
+
+(define-boxed-opaque-accessor text-iter text-iter-offset
+  :reader "gtk_text_iter_get_offset" :writer "gtk_text_iter_set_offset" :type :int)
+@end lisp
+
+@node boxed-related-symbols
+@section boxed-related-symbols
+
+@lisp
+(boxed-related-symbols name) @result{} symbols
+@end lisp
+
+@table @var
+@item @var{name}
+A symbol naming the boxed type
+@item @var{symbols}
+A list of symbols
+@end table
+
+This function returns the list of symbols that are related to GBoxed type @var{name}. These symbols are returned:
+@itemize
+@item name of boxed type
+@item name of all accessors of cstruct and variant-cstruct boxed types
+@item names of all variants of variant-cstruct boxed types
+@item names of constructors and copiers of cstruct and variant-cstruct boxed-types
+@end itemize
+
+Typical usage of this function is to export the symbols related to given boxed type.
 
 Example:
 @lisp
-(defcstruct tree-iter
-  (stamp :int)
-  (user-data :pointer)
-  (user-data-2 :pointer)
-  (user-data-3 :pointer))
-
-(defun tree-iter-get-stamp (i) (foreign-slot-value (pointer i) 'tree-iter 'stamp))
-(defun tree-iter-set-stamp (value i) (setf (foreign-slot-value (pointer i) 'tree-iter 'stamp) value))
-(defun tree-iter-get-user-data (i) (pointer-address (foreign-slot-value (pointer i) 'tree-iter 'user-data)))
-(defun tree-iter-set-user-data (value i) (setf (foreign-slot-value (pointer i) 'tree-iter 'user-data) (make-pointer value)))
-
-(defun tree-iter-alloc () (glib:g-malloc (foreign-type-size 'tree-iter)))
-(defun tree-iter-free (v) (glib:g-free v))
-
-(define-g-boxed-ref "GtkTreeIter" tree-iter
-  (:slots (stamp :reader tree-iter-get-stamp :writer tree-iter-set-stamp :accessor tree-iter-stamp)
-          (user-data :reader tree-iter-get-user-data :writer tree-iter-set-user-data :accessor tree-iter-user-data))
-  (:alloc-function tree-iter-alloc)
-  (:free-function tree-iter-free))
-@end lisp
-
-Another example:
-@lisp
-(define-foreign-type unichar ()
-  ()
-  (:actual-type :uint32)
-  (:simple-parser unichar))
-
-(defmethod translate-from-foreign (value (type unichar))
-  (code-char value))
-
-(defmethod translate-to-foreign (value (type unichar))
-  (char-code value))
-
-(define-g-boxed-ref "GtkTextIter" text-iter
-  (:free-function gtk-text-iter-free)
-  (:alloc-function gtk-text-iter-alloc)
-  (:slots (text-iter-buffer :reader "gtk_text_iter_get_buffer" :type (g-object text-buffer))
-          (text-iter-offset :reader "gtk_text_iter_get_offset" :writer "gtk_text_iter_set_offset" :type :int)
-          (text-iter-line :reader "gtk_text_iter_get_line" :writer "gtk_text_iter_set_line" :type :int)
-          (text-iter-line-offset :reader "gtk_text_iter_get_line_offset" :writer "gtk_text_iter_set_line_offset" :type :int)
-          (text-iter-visible-line-offset :reader "gtk_text_iter_get_visible_line_offset" :writer "gtk_text_iter_set_visible_line_offset" :type :int)
-          (text-iter-char :reader "gtk_text_iter_get_char" :type unichar)
-          (text-iter-pixbuf :reader "gtk_text_iter_get_pixbuf" :type (g-object pixbuf))
-          (text-iter-marks :reader "gtk_text_iter_get_marks" :type (gslist (g-object text-mark) :free-from-foreign t))
-          (text-iter-child-anchor :reader "gtk_text_iter_get_child_anchor" :type (g-object text-child-anchor))
-          (text-iter-tags :reader "gtk_text_iter_get_tags" :type (gslist (g-object text-tag) :free-from-foreign t))
-          (text-iter-chars-in-line :reader "gtk_text_iter_get_chars_in_line" :type :int)
-          (text-iter-language :reader "gtk_text_iter_get_language" :type :pointer)
-          (text-iter-is-end :reader "gtk_text_iter_is_end" :type :boolean)
-          (text-iter-is-start :reader "gtk_text_iter_is_start" :type :boolean)
-          (text-iter-can-insert :reader "gtk_text_iter_can_insert" :type :boolean)
-          (text-iter-starts-word :reader "gtk_text_iter_starts_word" :type :boolean)
-          (text-iter-ends-word :reader "gtk_text_iter_ends_word" :type :boolean)
-          (text-iter-inside-word :reader "gtk_text_iter_inside_word" :type :boolean)
-          (text-iter-starts-line :reader "gtk_text_iter_starts_line" :type :boolean)
-          (text-iter-ends-line :reader "gtk_text_iter_ends_line" :type :boolean)
-          (text-iter-starts-sentence :reader "gtk_text_iter_starts_sentence" :type :boolean)
-          (text-iter-ends-sentence :reader "gtk_text_iter_ends_sentence" :type :boolean)
-          (text-iter-inside-sentence :reader "gtk_text_iter_inside_sentence" :type :boolean)
-          (text-iter-is-cursor-position :reader "gtk_text_iter_is_cursor_position" :type :boolean)))
-
-(defcstruct %text-iter
-  (dummy1 :pointer)
-  (dummy2 :pointer)
-  (dummy3 :int)
-  (dummy4 :int)
-  (dummy5 :int)
-  (dummy6 :int)
-  (dummy7 :int)
-  (dummy8 :int)
-  (dummy9 :pointer)
-  (dummy10 :pointer)
-  (dummy11 :int)
-  (dummy12 :int)
-  (dummy13 :int)
-  (dummy14 :pointer))
-
-(defcfun gtk-text-iter-copy :pointer
-  (iter :pointer))
-
-(defcfun gtk-text-iter-free :void
-  (iter :pointer))
-
-(defun gtk-text-iter-alloc ()
-  (with-foreign-object (iter '%text-iter)
-    (gtk-text-iter-copy iter)))
+(define-g-boxed-cstruct rectangle "GdkRectangle"
+  (x :int :initform 0)
+  (y :int :initform 0)
+  (width :int :initform 0)
+  (height :int :initform 0))
+
+(boxed-related-symbols 'rectangle)
+@result{}
+(RECTANGLE MAKE-RECTANGLE COPY-RECTANGLE RECTANGLE-X RECTANGLE-Y
+ RECTANGLE-WIDTH RECTANGLE-HEIGHT)
+@end lisp
+
+@node GBoxed foreign type
+@section GBoxed foreign type
+
+@lisp
+(g-boxed-foreign name &rest option*)
+
+option ::= :return
+@end lisp
+
+@table @var
+@item @var{name}
+Name of GBoxed type
+@item @var{option}
+Option of foreign type
+@item @code{:return}
+An option that identifies the foreign type which is used at return position (as foreign function return type or as a callback return type)
+@end table
+
+@code{g-boxed-foreign} type deals with marshaling data between Lisp code and foreign code. The marshaling follows the following principles:
+@itemize
+@item All operations on Lisp objects corresponding to GBoxed types are type-safe and should never lead to any form of memory corruption (if some operation is impossible due to e.g., pointer in opaque pointer wrapper being invalidated, error should be signalled)
+@item Lisp objects should not be manually managed and are properly reclaimed by garbage collector, leaving no memory leaks
+@item Foreign code can change objects that are passed to them as arguments. This is required for functions that operate by modifying their arguments
+@item Lisp code in callbacks can change objects that are passed as arguments. This is required to be able to implement interfaces that have functions that operate by modifying their arguments
+@end itemize
+
+The @code{:return} option is required to be able to properly manage memory of opaque pointer wrappers and propagate changes to foreign and lisp structures.
+
+In order to be able to correctly use @code{g-boxed-foreign} foreign type in callbacks, you should use @code{glib-defcallback}. This macro is a thin wrapper around @code{cffi:defcallback} that adds proper handling of @code{g-boxed-foreign} foreign types.
+
+Examples of usage:
+@lisp
+(define-vtable ("GtkTreeModel" c-gtk-tree-model)
+  ...
+  (tree-model-get-path-impl tree-model-get-path-cb
+    (g-boxed-foreign tree-path :return) (tree-model g-object) (iter (g-boxed-foreign tree-iter)))
+  (tree-model-get-value-impl tree-model-get-value-cb
+    :void (tree-model g-object) (iter (g-boxed-foreign tree-iter)) (n :int) (value (:pointer g-value)))
+  (tree-model-iter-next-impl tree-model-iter-next-cb
+    :boolean (tree-model g-object) (iter (g-boxed-foreign tree-iter)))
+  ...)
+
+(defcfun gtk-text-iter-forward-search :boolean
+  (iter (g-boxed-foreign text-iter))
+  (str (:string :free-to-foreign t))
+  (flags text-search-flags)
+  (match-start (g-boxed-foreign text-iter))
+  (match-end (g-boxed-foreign text-iter))
+  (limit (g-boxed-foreign text-iter)))
 @end lisp
 
 @node Generating type definitions by introspection