Next: , Previous: define-g-boxed-cstruct, Up: GBoxed

12.2 define-g-boxed-variant-cstruct

— Macro: define-g-boxed-variant-cstruct
     (define-g-boxed-variant-cstruct name g-type-name
       &body slot-or-variant-specification*)
     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*)
A symbol naming the type being defined
A string specifying the GType name of this GBoxed. This may be nil if this type is not registered with GObject type system.
A symbol naming the slot of a structure
A foreign type of a slot
An integer. Corresponds to :count option of slot in CFFI defcstruct. If count is not NIL, then the slot is mapped to Lisp array.
A form that is the initform of Lisp structure slot
A boolean. If it is true, then the slot contains GBoxed structure whose name is slot-type.
A name of the dispatching slot
A single value or a list of values.
A symbol naming the structure

Defines the variant GBoxed structure. Slots of variant structures are defined the same way as the slots of “simple” cstructs. After the last slot, 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, GdkEvent structure has variants GdkEventAny, GdkEventButton, GdkEventMotion. In Lisp, event structure is defined with all common fields of these structures and event-button, event-motion structures inherit from 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).

This also defines the name-cstruct, structure-name-cstruct, structure-name-cunion CFFI structures definitions with equivalent structures (unions).

For example, for these structures this assumption holds:

     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;


     (define-g-boxed-variant-cstruct event "GdkEvent"
       (type event-type)
       (window (g-object gdk-window))
       (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))

This code defines following structures:

     (defstruct event
       type window send-event)
     (defstruct (event-key (:include event))
       time state keyval length string
       hardware-keycode group is-modifier)
     (defstruct (event-button (:include event))
       time x y axes state button device x-root y-root)