Table of Contents
Libraries and Saved Images
Defining a library
(ffi:define-foreign-library libfreetype
(:darwin (:or "libfreetype.6.dylib" "libfreetype.dylib"))
(:windows (:or "C:/path/to/native/freetype.dll" "freetype.dll"))
(:unix (:or "libfreetype.so.6" "libfreetype.so"))
(t (:default "libfreetype")))
Each clause is (condition spec), and the first whose condition holds
says what to load.
- A condition is
t, a keyword, or(:or ...),(:and ...)and(:not ...)of them. A keyword is one of cl-ffi's platform keywords,:windows,:unix,:linuxand:darwin, or a feature in*features*.:windowsholds on Windows, though SBCL sets only:win32. - A spec is a file name the system searches for, such as
"libz.so.1", or a full path;(:or spec...)to try one after the other; or(:default "name")forname.so,name.dllorname.dylib.
cl-ffi has no list of directories of its own: where a library is outside the system's search path, give its full path, or put its directory on the system's search path.
Loading
(ffi:use-foreign-library libfreetype) ; at top level, when the file loads
(ffi:load-foreign-library 'libfreetype) ; when called
(ffi:load-foreign-library "libicui18n.so.78") ; a library of no name, from a spec
load-foreign-library loads a library unless it is loaded, and returns its
designator and the file it was loaded from. Besides a defined name it
takes a spec, for a library whose file name is known only at run time.
foreign-library-loaded-p and foreign-library-pathname take either, and
say whether and from which file.
A library that cannot be loaded signals a load-foreign-library-error,
whose report lists each file tried with the system's reason:
Could not load the foreign library LIBMISSING.
libmissing.so.1: Error opening shared object "libmissing.so.1": libmissing.so.1: cannot open shared object file: No such file or directory.
libmissing.so: Error opening shared object "libmissing.so": libmissing.so: cannot open shared object file: No such file or directory.
A binding usually catches it and adds what to install. It is signalled once cl-ffi has let go of the lock it loads libraries under, so a handler, or the debugger, may load another library in its place:
(handler-case (ffi:load-foreign-library 'libfreetype)
(ffi:load-foreign-library-error ()
(ffi:load-foreign-library "C:/bundled/freetype.dll")))
Any thread may load libraries; one loads at a time.
Saved images
SBCL reopens the shared objects of a saved image by the paths they were
loaded from, which on another machine may not exist. cl-ffi does not let
it: when a saved image starts, it loads each library it loaded again, in
the order it first loaded them, from its definition or spec, so a library
first loaded by a developer's full path is found by name on a player's
machine. Then it looks every callback's pointer up again, and runs the
functions add-image-start-hook added, in the order they were added:
(ffi:add-image-start-hook 'find-functions-again)
A hook is for state about foreign code that the new process must find again, such as pointers looked up in a library by a computed name. What cannot be loaded, or a hook that fails, is reported as a warning, and the rest go on.
cl-ffi loads libraries with SBCL's :dont-save, so SBCL leaves them to
cl-ffi to load again. A library a program loads through cffi beside
cl-ffi is not cl-ffi's to reload.