Defines a FLI structure type specifier corresponding to the C struct
type.
fli
define-c-struct name-and-options &rest descriptions => list
name-and-options ::= name | (name option*)
option ::= (:foreign-name foreign-name) | (:forward-reference-p forward-reference-p)
descriptions ::= {slot-description | byte-packing | aligned}*
slot-description ::= (slot-name slot-type)
byte-packing ::= (:byte-packing nbytes)
aligned ::= (:aligned nbytes)
name⇩ |
A symbol naming the new structure type specifier. |
foreign-name⇩ |
A string specifying the foreign name of the structure. |
forward-reference-p⇩ |
A boolean. |
byte-packing⇩ |
A list specifying byte packing for the subsequent slots. |
slot-name⇩ |
A symbol naming the slot. |
slot-type⇩ |
The foreign type of the slot. |
nbytes⇩ |
The number of 8-bit bytes to pack. |
list |
The list (:struct name) . |
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 foreign-slot-type and foreign-slot-value functions.
The FLI type specifier is named by name, with optional foreign name foreign-name.
Each slot-description is a list of a symbol slot-name and a corresponding FLI type descriptor slot-type which is the type of the slot named by slot-name.
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.
An aligned form specifies that the next slot must be aligned on nbytes bytes. Note that this affects only the alignment of the next slot. It does not affect the length of the slot, or the alignment of other slots. You will need this when the slot is made to be aligned, for example in gcc
a slot defined like this:
int slot_name __attribute__ ((aligned (16))) ;
needs to be aligned on 16 bytes, even though the native alignment of the type int
is 4.
When forward-reference-p is true, the new type specifier is defined as a forward reference type and descriptions can be empty. See define-foreign-forward-reference-type.
foreign-name, specifying the foreign name, is supported only for documentation purposes.
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 byte-packing, 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
2 FLI Types
Foreign Language Interface User Guide and Reference Manual - 01 Dec 2021 19:34:58