I don't know whether this is possible in SBCL. To make it possible it would at least be necessary to allocate arrays in such a way that the GC doesn't move them. The SBCL manual contains a reference to a macro sb-sys:with-pinned-objects
which might do this, but there doesn't seem to be any other information there.
However when I've needed to do something like this I've done it backwards: create a suitable object at the C level, and then wrap it with Lisp code to access it. The advantage of this is that you know how to deal with it from C, the disadvantage is that it's not an array, so you have to write your own access functions: things like read-sequence
aren't going to work and so on.
I ended up using structures which wrapped alien vectors: here is a chunk of the code I used to deal with arrays of signed bytes:
(deftype index ()
`(integer 0 (,most-positive-fixnum)))
...
(defstruct (foreign-octet-vector
(:constructor %make-foreign-octet-vector (octets size)))
(octets (error "no")
:type (alien (* (signed 8)))
:read-only t)
(size 0
:type index
:read-only t))
(defun make-foreign-octet-vector (size)
(%make-foreign-octet-vector
(make-alien (signed 8) size)
size))
(defun free-foreign-octet-vector (v)
(free-alien (foreign-octet-vector-octets v))
nil)
(declaim (inline fov-ref (setf fov-ref)))
(defun fov-ref (v n)
(declare (type foreign-octet-vector v)
(type index n))
(if (< n (foreign-octet-vector-size v))
(deref (foreign-octet-vector-octets v) n)
(error "out of range")))
(defun (setf fov-ref) (value v n)
(declare (type foreign-octet-vector v)
(type index n)
(type (signed-byte 8) value))
(if (< n (foreign-octet-vector-size v))
(setf (deref (foreign-octet-vector-octets v) n) value)
(error "out of range")))
On top of this there was a fairly obvious macro using unwind-protect
to make sure things got deallocated.
I don't know if this is either idiosyncratic SBCL code, or actually correct in general, but it worked for me. It may be that CFFI provides some better interface to all this.