define-c-struct name-and-options &rest descriptions => list
name-and-options ::= name | ( name option *)
option ::= (:foreign-name string )
descriptions ::= { slot-description | byte-packing }*
slot-description ::= { slot-name | ( slot-name slot-type )}
A symbol naming the new structure type specifier
A string specifying the foreign name of the structure.
A symbol, or a list of symbol and type description, naming a slot in the structure
A symbol naming the slot
The foreign type of the slot
A list specifying byte packing for the subseqent slots
The number of 8-bit bytes to pack
The macro
define-c-struct
is used to define a FLI structure type specifier, which corresponds to the C
struct
type. It is a convenience function, as a structure type could also be defined using define-foreign-type.
A structure is an aggregate type, or collection, of other FLI types. The types contained in a structure are referred to as slots, and can be accessed using the define-foreign-type and foreign-slot-value functions.
Some C compilers support pragmas such as
#pragma pack(1)
which causes fields in a structure to be aligned on a byte boundary even if their natural alignment is larger. This can be achieved from Lisp by specifying suitable
byte-packing
forms in the structure definition, as in the example below. Each
byte-packing
form specifies the packing for each
slot-description
that follows it in the
define-c-struct
form. It is important to use the same packing as the C header file containing the foreign type.
The first example shows a C structure definition and the corresponding FLI definition:
struct a-point {
int x;
int y;
byte color;
char ident;
};
(fli:define-c-struct a-point (x :int)
(y :int)
(color :byte)
(ident :char))
The second example shows how you might retrieve data in Lisp from a C function that returns a structure:
struct 3dvector
{
float x;
float y;
float z;
}
static 3dvector* vector;
3dvector* fn ()
{
return vector;
}
(fli:define-c-struct 3dvector
(x :float)
(y :float)
(z :float))
(fli:define-foreign-function fn ()
:result-type (:pointer (:struct 3dvector)))
(let ((vector (fn)))
(fli:with-foreign-slots (x y z) vector
(values x y z)))
Finally an example to illustrate byte packing. This structure will require 4 bytes of memory because the field named a-short will be aligned on a 2 byte boundary and hence a byte will be wasted after the a-byte field:
(fli:define-c-struct foo ()
(a-byte (:unsigned :byte))
(a-short (:unsigned :short)))
After adding the byte-packing form, the structure will require only 3 bytes:
(fli:define-c-struct foo
(:byte-packing 1)
(a-byte (:unsigned :byte))
(a-short (:unsigned :short)))
define-c-enum
define-c-typedef
define-c-union
define-foreign-type
foreign-slot-names
foreign-slot-type
foreign-slot-value