4.3 The C-to-FFI facility
:output-file :case-sensitive :defines-too :compile :thing :loud :ansi-c
:compilekeyword is non-
:output-file, it defaults to the C filename ending in .lisp, as in foo.c becoming foo.lisp. If it is the symbol
t, then output is written to
*standard-output*instead of a file.
nil, the Lisp code produced will have exactly the same case as the original C code, and that case will be preserved by the Lisp reader. This means that most symbols will be printed surrounded by vertical bars. If the value of
nil(the default), the Lisp code produced will have the same case as the original C code, but that case will not be preserved by the Lisp reader.
:includeis supplied, it should be a list of directory names that would normally be passed to
-Iarguments when compiling the given C file. This is where the
#include'd files exist. (We need this because we invoke the C preprocessor
cppon the file.) If a value for
:includeis not supplied, it defaults to the directory of c-filename.
nil, the translation will contain text from files included using
#include. If it is
nil, only the text within the file specified will be translated. The value of
nil. (Note that the include search path specified by
:includeis still needed even if the value of
nil, because the include files may contain definitions that are necessary to process the file.)
t(the default), then we translate simple
defconstantcalls. This does not attempt to translate C macros that take arguments.
#includedirectories. If calls to
typedefare not made before the defined types are first used, then ambiguity arises and we cannot reliably parse C. Likewise, unexpanded preprocessor macros will cause parse errors.
t, we call
compile-fileon the Lisp file after writing it.
:thingis what to extract from c-filename; it defaults to
:all, meaning that it produces FFI calls for everything in the C file (and in the files
#include'd by it, if the value of
nil). It may be a string or list of strings, which are the names of structures, functions, or variables which we should translate. However, we also translate all user-defined structures and types which are referenced by the specified thing--if a function returns a pointer to a structure, then the definition of that structure will be translated as well.
t, then some progress messages will be written on
*standard-output*. If it is
:very, then a C-syntax representation of everything being parsed will be printed. This can be useful for debugging.
:ansi-creflects whether you use an ANSI C compiler. The value should be
tif you do and
nilif you don't. It defaults to the value of
translate-c-file, you must use
lcl:load-foreign-librariesto read in the
.afile corresponding to the C code which you have translated. If you don't do this, then Lisp can't determine the addresses of the global variables referenced declared in C and can't make pointers to them.
.cfiles as well as
.hfiles, even if all of the functions you wish to use are declared in the
.hfiles. Non-ANSI header files do not contain type declarations for the arguments of functions, and Lisp needs to know them.
.hfile in your system--simply running it on a file which
#include's the header files you wish to translate will do, since
#include'd files are spliced in by
;;; Assume we begin with the C function: ;;; int ThisIsATest (); ;;; defined in the file test.c ;;; The default case-sensitive value of nil produces ;;; more readable code, but has the potential of producing ;;; ambiguous results, since C is strictly case-sensitive. ;;; Then the following Lisp code will be produced: (def-foreign-function (ThisIsATest (:name "_ThisIsATest") (:return-type :signed-32bit)))*cpp-command* Variable
;;; Now we call translate-c-file with :case-sensitive true. (translate-c-file "test.c" :case-sensitive t)
(def-foreign-function (|ThisIsATest| (:name "_ThisIsATest") (:return-type :signed-32bit)))
-E. Do not include in this list the switch that inhibits line numbering (normally
int a;says that the variable
aholds storage for 50 integers. The expression
aas a one-dimensional array of arrays, and refers to the array in the third row. The expression
acan be viewed as either accessing slot (3, 3) in a 5x10 array, or accessing slot 3 of the array in slot 3 of a one-dimensional array.
t(the default), then the type of
int awill be
(:array :signed-32bit (5 10)). If it is
nil, then the Foreign Function Interface type will instead be
(:array (:array :signed-32bit (10)) (5)).
def-foreign-function. On Solaris, this function is an identity. This may have to be changed to match your C compiler.
> (apply c-to-ffi:*make-linker-name* '("my-function")) "my-function"
:struct-slot. Each of these three keywords represents a context where one can specify:
type char *
:function, which specifies function return values
:argument, which specifies function arguments
:struct-slot, which specifies structure slots
(:pointer :character)in the corresponding C context.
:stringallows you to use a Lisp string in a context where a foreign pointer would otherwise be necessary.
int vowel_count (char * word);
(def-foreign-function (vowel_count (:name "vowel_count") (:return-type :signed-32bit)) (word (:pointer : character)))
nil, the result is:
(def-foreign-function (vowel_count (:name "vowel_count") (:return-type :signed-32bit)) (word :string))
*default-archive-directories*contains a list of directories that are searched by the functions
(.a)files. When a library name, such as
-lc, is specified, the full library name is formed by removing
-lfrom the name, prepending the directory name, and appending the suffix
> (pprint *default-archive-directories*) ("/usr/lib/lib" "/opt/SUNWspro/SC2.0.1/lib" "/opt/SUNWspro/SC2.0/lib" "/usr/ccs/lib/lib" "/usr/ucblib/lib" "/usr/local/lib/lib")*ansi-c* Variable
;; Note that /opt/SUNWspro/SC2.0/libm.a is a symbolic link to ;; ./cg89/libm.a > (let ((*default-archive-directories* '("/usr/lib/lib" "/opt/SUNWspro/SC2.0/lib" "/optf77/SUNWspro/SC2.0.1/lib"))) (load-foreign-files '("ftnf.o" "ftng.o") '("-lM77" "-lF77" "-lV77" "-lm" "-lc"))) ;;; Loading foreign object file "ftnf.o" ;;; Loading foreign object file "ftng.o" ;;; Reading library file "/optf77/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/optf77/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/optf77/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" T
t(the default) if you are using an ANSI C compiler; otherwise, use
nil. Liquid Common Lisp needs to know whether you are using an ANSI C compiler or not, as some non-ANSI compilers are known to have problems with single floats. Using this variable will avoid those problems.
Generated with Harlequin WebMaker