Next: , Previous: defbitfield, Up: Foreign Types


defcstruct

Syntax

— Macro: defcstruct name-and-options &body doc-and-slots => name

name-and-options ::= structure-name | (structure-name &key size)

doc-and-slots ::= [docstring] { (slot-name slot-type &key count offset) }*

Arguments and Values

structure-name
The name of new structure type.
docstring
A documentation string, ignored.
slot-name
A symbol naming the slot. It must be unique among slot names in this structure.
size
Use this option to override the size (in bytes) of the struct.
slot-type
The type specifier for the slot.
count
Used to declare an array of size count inside the structure. Defaults to 1 as such an array and a single element are semantically equivalent.
offset
Overrides the slot's offset. The next slot's offset is calculated based on this one.

Description

This defines a new CFFI aggregate type akin to C structs. In other words, it specifies that foreign objects of the type structure-name are groups of different pieces of data, or “slots”, of the slot-types, distinguished from each other by the slot-names. Each structure is located in memory at a position, and the slots are allocated sequentially beginning at that point in memory (with some padding allowances as defined by the C ABI, unless otherwise requested by specifying an offset from the beginning of the structure (offset 0).

In other words, it is isomorphic to the C struct, giving several extra features.

There are two kinds of slots, for the two kinds of CFFI types:

Simple
Contain a single instance of a type that canonicalizes to a built-in type, such as :long or :pointer. Used for simple CFFI types.
Aggregate
Contain an embedded structure or union, or an array of objects. Used for aggregate CFFI types.

The use of CLOS terminology for the structure-related features is intentional; structure definitions are very much like classes with (far) fewer features.

Examples

  (defcstruct point
    "Pointer structure."
    (x :int)
    (y :int))
   
  CFFI> (with-foreign-object (ptr 'point)
          ;; Initialize the slots
          (setf (foreign-slot-value ptr 'point 'x) 42
                (foreign-slot-value ptr 'point 'y) 42)
          ;; Return a list with the coordinates
          (with-foreign-slots ((x y) ptr point)
            (list x y)))
  => (42 42)
  ;; Using the :size and :offset options to define a partial structure.
  ;; (this is useful when you are interested in only a few slots
  ;; of a big foreign structure)
   
  (defcstruct (foo :size 32)
    "Some struct with 32 bytes."
                          ; <16 bytes we don't care about>
    (x :int :offset 16)   ; an int at offset 16
    (y :int)              ; another int at offset 16+sizeof(int)
                          ; <a couple more bytes we don't care about>
    (z :char :offset 24)  ; a char at offset 24
                          ; <7 more bytes ignored (since size is 32)>
    )
   
  CFFI> (foreign-type-size 'foo)
  => 32

See Also

foreign-slot-pointer
foreign-slot-value
with-foreign-slots