While the foreign function invocation protocols differ strongly between platforms and implementations, foreign objects are pretty easy to handle portably. For ECL, a foreign object is just a bunch of bytes stored in memory. The lisp object for a foreign object encapsulates several bits of information:
A list or a symbol specifying the C type of the object.
The pointer to the region of memory where data is stored.
A flag determining whether ECL can automatically manage that piece of memory and deallocated when no longer in use.
A foreign object may contain many different kinds of data: integers, floating point numbers, C structures, unions, etc. The actual type of the object is stored in a list or a symbol which is understood by the higher level interface (Section 3.4).
The most important component of the object is the memory region where
data is stored. By default ECL assumes that the user will perform automatic
managment of this memory, deleting the object when it is no longer
needed. The first reason is that this block may have been allocated by a
foreign routine using malloc()
, or
mmap()
, or statically, by referring to a C constant. The
second reason is that foreign functions may store references to this memory
which ECL is not aware of and, in order to keep these references valid,
ECL should not attempt to automatically destroy the object.
In many cases, however, it is desirable to automatically destroy
foreign objects once they have been used. The higher level interfaces UFFI
and CFFI provide tools for doing this. For instance, in the following
example adapted from the UFFI documentation, the string
NAME
is automatically deallocated
(def-function "gethostname" ((name (* :unsigned-char)) (len :int)) :returning :int) (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256)) (format t "Hostname: ~S" (ffi:convert-from-foreign-string name)) (error "gethostname() failed."))