Table of Contents
Memory
Pointers
A foreign pointer is SBCL's system-area pointer; the type foreign-pointer
names it. null-pointer, null-pointer-p, pointerp, pointer-eq,
pointer-address, make-pointer and inc-pointer (whose offset may be
negative) make and compare them.
A pointer make-pointer makes from an integer address and only reads or
writes through allocates nothing:
(ffi:mem-ref (ffi:make-pointer address) :uint32 4)
Reading and writing
(ffi:mem-ref pointer :uint32) ; at the pointer
(ffi:mem-ref pointer :double 8) ; 8 bytes past it
(setf (ffi:mem-aref pointer :int16 3) -1) ; element 3 of an array of int16
(ffi:mem-aptr pointer '(:struct point) 2) ; a pointer to element 2
mem-ref and mem-aref read scalars, enums, bitfields and booleans, and
setf writes them. With a constant type each compiles to one memory
access. mem-aptr takes any type, structs included.
The heap
(foreign-alloc type &key count initial-element) allocates with malloc:
count elements, filled with initial-element if it is given and
otherwise as malloc leaves them. foreign-free frees. Running out of
memory signals an ffi-error.
The stack
(ffi:with-foreign-object (rect '(:struct rect))
(get-client-rect window rect)
(ffi:foreign-slot-value rect '(:struct rect) 'right))
(ffi:with-foreign-objects ((width :int) (height :int))
...)
(ffi:with-foreign-pointer (buffer 256 size)
...)
with-foreign-object gives count elements of a type, and
with-foreign-pointer a number of bytes, for the extent of the body,
aligned to 8 bytes and not cleared. They are on the stack when the size is
a constant; a size known only at run time comes from malloc and is freed
when the body returns.
Lisp vectors
(let ((pixels (make-array (* 4 width height) :element-type '(unsigned-byte 8))))
(ffi:with-pointer-to-vector-data (pointer pixels)
(read-pixels pointer))
pixels)
with-pointer-to-vector-data lends C the elements of a simple vector of a
specialized numeric element type, without copying. The vector stays in
place for the extent of the body.
Allocation
What code that runs every frame uses allocates nothing, and the tests
measure it: mem-ref, mem-aref, foreign-slot-value and their setf
forms with constant types, with-foreign-object of a constant size, on
the stack, and of a size given at run time, from malloc, calls through
foreign-funcall and foreign-funcall-pointer of numbers and pointers,
and reading through a pointer make-pointer made from an address.
On SBCL, a pointer to stack or malloc'd memory passed to a function that is not inlined is boxed, 16 bytes. A binding's per-frame functions should therefore be declared inline, as cl-vk's commands, cl-icu's functions and cl-harfbuzz's raw bindings are.