(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*)
:count
option of slot in CFFI defcstruct
. If count
is not NIL, then the slot is mapped to Lisp array.
slot-type
.
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; ... };
Example:
(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)