dotfiles/sbcl/.quicklisp/dists/quicklisp/software/cffi_0.20.1/doc/cffi-manual.texinfo

7114 lines
214 KiB
Text
Raw Normal View History

2020-02-18 14:21:14 -05:00
\input texinfo @c -*- Mode: Texinfo; Mode: auto-fill -*-
@c %**start of header
@setfilename cffi.info
@settitle CFFI User Manual
@exampleindent 2
@c @documentencoding utf-8
@c Style notes:
@c
@c * The reference section names and "See Also" list are roman, not
@c @code. This is to follow the format of CLHS.
@c
@c * How it looks in HTML is the priority.
@c ============================= Macros =============================
@c The following macros are used throughout this manual.
@macro Function {args}
@defun \args\
@end defun
@end macro
@macro Macro {args}
@defmac \args\
@end defmac
@end macro
@macro Accessor {args}
@deffn {Accessor} \args\
@end deffn
@end macro
@macro GenericFunction {args}
@deffn {Generic Function} \args\
@end deffn
@end macro
@macro ForeignType {args}
@deftp {Foreign Type} \args\
@end deftp
@end macro
@macro Variable {args}
@defvr {Special Variable} \args\
@end defvr
@end macro
@macro Condition {args}
@deftp {Condition Type} \args\
@end deftp
@end macro
@macro cffi
@acronym{CFFI}
@end macro
@macro impnote {text}
@quotation
@strong{Implementor's note:} @emph{\text\}
@end quotation
@end macro
@c Info "requires" that x-refs end in a period or comma, or ) in the
@c case of @pxref. So the following implements that requirement for
@c the "See also" subheadings that permeate this manual, but only in
@c Info mode.
@ifinfo
@macro seealso {name}
@ref{\name\}.
@end macro
@end ifinfo
@ifnotinfo
@alias seealso = ref
@end ifnotinfo
@c Typeset comments in roman font for the TeX output.
@iftex
@alias lispcmt = r
@end iftex
@ifnottex
@alias lispcmt = asis
@end ifnottex
@alias res = result
@c ============================= Macros =============================
@c Show types, functions, and concepts in the same index.
@syncodeindex tp cp
@syncodeindex fn cp
@copying
Copyright @copyright{} 2005 James Bielman <jamesjb at jamesjb.com> @*
Copyright @copyright{} 2005-2015 Lu@'{@dotless{i}}s Oliveira
<loliveira at common-lisp.net> @*
Copyright @copyright{} 2005-2006 Dan Knapp <danka at accela.net> @*
Copyright @copyright{} 2005-2006 Emily Backes <lucca at accela.net> @*
Copyright @copyright{} 2006 Stephen Compall <s11 at member.fsf.org>
@quotation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
@sc{The software is provided ``as is'', without warranty of any kind,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose and noninfringement.
In no event shall the authors or copyright holders be liable for any
claim, damages or other liability, whether in an action of contract,
tort or otherwise, arising from, out of or in connection with the
software or the use or other dealings in the software.}
@end quotation
@end copying
@c %**end of header
@dircategory Software development
@direntry
* CFFI Manual: (cffi-manual). CFFI Manual.
@end direntry
@titlepage
@title CFFI User Manual
@c @subtitle Version X.X
@c @author James Bielman
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@contents
@ifnottex
@node Top, Introduction, (dir), (dir)
@top cffi
@insertcopying
@end ifnottex
@menu
* Introduction:: What is CFFI?
* Installation::
* Implementation Support::
* Tutorial:: Interactive intro to using CFFI.
* Wrapper generators:: CFFI forms from munging C source code.
* Foreign Types::
* Pointers::
* Strings::
* Variables::
* Functions::
* Libraries::
* Callbacks::
* The Groveller::
* Static Linking::
* Limitations::
* Platform-specific features:: Details about the underlying system.
* Glossary:: List of CFFI-specific terms and meanings.
* Comprehensive Index::
@detailmenu
--- Dictionary ---
Foreign Types
* convert-from-foreign:: Outside interface to backward type translator.
* convert-to-foreign:: Outside interface to forward type translator.
* defbitfield:: Defines a bitfield.
* defcstruct:: Defines a C structure type.
* defcunion:: Defines a C union type.
* defctype:: Defines a foreign typedef.
* defcenum:: Defines a C enumeration.
* define-foreign-type:: Defines a foreign type specifier.
* define-parse-method:: Specifies how a type should be parsed.
@c * explain-foreign-slot-value:: <unimplemented>
* foreign-bitfield-symbols:: Returns a list of symbols for a bitfield type.
* foreign-bitfield-value:: Calculates a value for a bitfield type.
* foreign-enum-keyword:: Finds a keyword in an enum type.
* foreign-enum-value:: Finds a value in an enum type.
* foreign-slot-names:: Returns a list of slot names in a foreign struct.
* foreign-slot-offset:: Returns the offset of a slot in a foreign struct.
* foreign-slot-pointer:: Returns a pointer to a slot in a foreign struct.
* foreign-slot-value:: Returns the value of a slot in a foreign struct.
* foreign-type-alignment:: Returns the alignment of a foreign type.
* foreign-type-size:: Returns the size of a foreign type.
* free-converted-object:: Outside interface to typed object deallocators.
* free-translated-object:: Defines how to free a oreign object.
* translate-from-foreign:: Defines a foreign-to-Lisp object translation.
* translate-to-foreign:: Defines a Lisp-to-foreign object translation.
* with-foreign-object:: Allocates a foreign object with dynamic extent.
* with-foreign-objects:: Plural form of @code{with-foreign-object}.
* with-foreign-slots:: Accesses the slots of a foreign structure.
Pointers
* foreign-free:: Deallocates memory.
* foreign-alloc:: Allocates memory.
* foreign-symbol-pointer:: Returns a pointer to a foreign symbol.
* inc-pointer:: Increments the address held by a pointer.
* incf-pointer:: Increments the pointer address in a place.
* make-pointer:: Returns a pointer to a given address.
* mem-aptr:: The pointer to an element of an array.
* mem-aref:: Accesses the value of an index in an array.
* mem-ref:: Dereferences a pointer.
* null-pointer:: Returns a NULL pointer.
* null-pointer-p:: Tests a pointer for NULL value.
* pointerp:: Tests whether an object is a pointer or not.
* pointer-address:: Returns the address pointed to by a pointer.
* pointer-eq:: Tests if two pointers point to the same address.
* with-foreign-pointer:: Allocates memory with dynamic extent.
Strings
* *default-foreign-encoding*:: Default encoding for the string types.
* foreign-string-alloc:: Converts a Lisp string to a foreign string.
* foreign-string-free:: Deallocates memory used by a foreign string.
* foreign-string-to-lisp:: Converts a foreign string to a Lisp string.
* lisp-string-to-foreign:: Copies a Lisp string into a foreign string.
* with-foreign-string:: Allocates a foreign string with dynamic extent.
* with-foreign-strings:: Plural form of @code{with-foreign-string}.
* with-foreign-pointer-as-string:: Similar to CL's with-output-to-string.
Variables
* defcvar:: Defines a C global variable.
* get-var-pointer:: Returns a pointer to a defined global variable.
Functions
* defcfun:: Defines a foreign function.
* foreign-funcall:: Performs a call to a foreign function.
* foreign-funcall-pointer:: Performs a call through a foreign pointer.
* translate-camelcase-name:: Converts a camelCase foreign name to/from a Lisp name.
* translate-name-from-foreign:: Converts a foreign name to a Lisp name.
* translate-name-to-foreign:: Converts a Lisp name to a foreign name.
* translate-underscore-separated-name:: Converts an underscore_separated foreign name to/from a Lisp name.
Libraries
* close-foreign-library:: Closes a foreign library.
* *darwin-framework-directories*:: Search path for Darwin frameworks.
* define-foreign-library:: Explain how to load a foreign library.
* *foreign-library-directories*:: Search path for shared libraries.
* load-foreign-library:: Load a foreign library.
* load-foreign-library-error:: Signalled on failure of its namesake.
@c * reload-foreign-libraries:: Reload foreign libraries.
* use-foreign-library:: Load a foreign library when needed.
Callbacks
* callback:: Returns a pointer to a defined callback.
* defcallback:: Defines a Lisp callback.
* get-callback:: Returns a pointer to a defined callback.
@end detailmenu
@end menu
@c ===================================================================
@c CHAPTER: Introduction
@node Introduction, Installation, Top, Top
@chapter Introduction
@cffi{} is the Common Foreign Function Interface for @acronym{ANSI}
Common Lisp systems. By @dfn{foreign function} we mean a function
written in another programming language and having different data and
calling conventions than Common Lisp, namely, C. @cffi{} allows you
to call foreign functions and access foreign variables, all without
leaving the Lisp image.
We consider this manual ever a work in progress. If you have
difficulty with anything @cffi{}-specific presented in the manual,
please contact @email{cffi-devel@@common-lisp.net,the developers} with
details.
@heading Motivation
@xref{Tutorial-Comparison,, What makes Lisp different}, for
an argument in favor of @acronym{FFI} in general.
@cffi{}'s primary role in any image is to mediate between Lisp
developers and the widely varying @acronym{FFI}s present in the
various Lisp implementations it supports. With @cffi{}, you can
define foreign function interfaces while still maintaining portability
between implementations. It is not the first Common Lisp package with
this objective; however, it is meant to be a more malleable framework
than similar packages.
@heading Design Philosophy
@itemize
@item
Pointers do not carry around type information. Instead, type
information is supplied when pointers are dereferenced.
@item
A type safe pointer interface can be developed on top of an
untyped one. It is difficult to do the opposite.
@item
Functions are better than macros. When a macro could be used
for performance, use a compiler-macro instead.
@end itemize
@c ===================================================================
@c CHAPTER: Installation
@node Installation, Implementation Support, Introduction, Top
@chapter Installation
@cffi{} can be obtained through one of the following means available
through its @uref{http://common-lisp.net/project/cffi/,,website}:
@itemize
@item
@uref{http://common-lisp.net/project/cffi/releases/?M=D,,official release
tarballs}
@item
@uref{http://common-lisp.net/gitweb?p=projects/cffi/cffi.git,,git
repository}
@c snapshots have been disabled as of
@c @item
@c @uref{http://common-lisp.net/project/cffi/tarballs/?M=D,,nightly-generated
@c snapshots}
@end itemize
In addition, you will need to obtain and install the following
dependencies:
@itemize
@item
@uref{http://common-lisp.net/project/babel/,,Babel}, a charset
encoding/decoding library.
@item
@uref{http://common-lisp.net/project/alexandria/,,Alexandria}, a
collection of portable public-domain utilities.
@item
@uref{http://www.cliki.net/trivial-features,,trivial-features}, a
portability layer that ensures consistent @code{*features*} across
multiple Common Lisp implementations.
@end itemize
Furthermore, if you wish to run the testsuite,
@uref{http://www.cliki.net/rt,,RT} is required.
You may find mechanisms such as
@uref{https://www.quicklisp.org/beta/,Quicklisp} (recommended)
or @uref{http://common-lisp.net/project/clbuild/,,clbuild} (for advanced
uses) helpful in getting and managing @cffi{} and its
dependencies.
@c ===================================================================
@c CHAPTER: Implementation Support
@node Implementation Support, Tutorial, Installation, Top
@chapter Implementation Support
@cffi{} supports various free and commercial Lisp implementations:
@acronym{ABCL}, Allegro CL, Clasp, @sc{clisp}, Clozure CL,
@acronym{CMUCL}, Corman CL, @acronym{ECL}, @acronym{GCL}, LispWorks,
@acronym{MCL}, @acronym{SBCL} and the Scieneer CL.
In general, you should work with the latest versions of each
implementation since those will usually be tested against recent
versions of CFFI more often and might include necessary features or
bug fixes. Reasonable patches for compatibility with earlier versions
are welcome nevertheless.
@section Limitations
Some features are not supported in all implementations.
@c TODO: describe these features here.
@c flat-namespace too
@subheading Allegro CL
@itemize
@item
Does not support the @code{:long-long} type natively.
@item
Unicode support is limited to the Basic Multilingual Plane (16-bit
code points).
@end itemize
@subheading Clasp
@itemize
@item
Only supports a flat namespace.
@end itemize
@subheading CMUCL
@itemize
@item
No Unicode support. (8-bit code points)
@end itemize
@subheading Corman CL
@itemize
@item
Does not support @code{foreign-funcall}.
@end itemize
@subheading @acronym{ECL}
@itemize
@item
On platforms where ECL's dynamic FFI is not supported (ie. when
@code{:dffi} is not present in @code{*features*}),
@code{cffi:load-foreign-library} does not work and you must use ECL's
own @code{ffi:load-foreign-library} with a constant string argument.
@end itemize
@subheading Lispworks
@itemize
@item
Does not completely support the @code{:long-long} type natively in
32-bit platforms.
@item
Unicode support is limited to the Basic Multilingual Plane (16-bit
code points).
@end itemize
@subheading @acronym{SBCL}
@itemize
@item
Not all platforms support callbacks.
@end itemize
@c ===================================================================
@c CHAPTER: An Introduction to Foreign Interfaces and CFFI
@c This macro is merely a marker that I don't think I'll use after
@c all.
@macro tutorialsource {text}
@c \text\
@end macro
@c because I don't want to type this over and over
@macro clikicffi
http://www.cliki.net/CFFI
@end macro
@c TeX puts spurious newlines in when you use the above macro
@c in @examples &c. So it is expanded below in some places.
@node Tutorial, Wrapper generators, Implementation Support, Top
@chapter An Introduction to Foreign Interfaces and @acronym{CFFI}
@c Above, I don't use the cffi macro because it breaks TeX.
@cindex tutorial, @cffi{}
Users of many popular languages bearing semantic similarity to Lisp,
such as Perl and Python, are accustomed to having access to popular C
libraries, such as @acronym{GTK}, by way of ``bindings''. In Lisp, we
do something similar, but take a fundamentally different approach.
This tutorial first explains this difference, then explains how you
can use @cffi{}, a powerful system for calling out to C and C++ and
access C data from many Common Lisp implementations.
@cindex foreign functions and data
The concept can be generalized to other languages; at the time of
writing, only @cffi{}'s C support is fairly complete. Therefore, we
will interchangeably refer to @dfn{foreign functions} and @dfn{foreign
data}, and ``C functions'' and ``C data''. At no time will the word
``foreign'' carry its usual, non-programming meaning.
This tutorial expects you to have a working understanding of both
Common Lisp and C, including the Common Lisp macro system.
@menu
* Tutorial-Comparison:: Why FFI?
* Tutorial-Getting a URL:: An FFI use case.
* Tutorial-Loading:: Load libcurl.so.
* Tutorial-Initializing:: Call a function in libcurl.so.
* Tutorial-easy_setopt:: An advanced libcurl function.
* Tutorial-Abstraction:: Why breaking it is necessary.
* Tutorial-Lisp easy_setopt:: Semi-Lispy option interface.
* Tutorial-Memory:: In C, you collect the garbage.
* Tutorial-Callbacks:: Make useful C function pointers.
* Tutorial-Completion:: Minimal get-url functionality.
* Tutorial-Types:: Defining new foreign types.
* Tutorial-Conclusion:: What's next?
@end menu
@node Tutorial-Comparison, Tutorial-Getting a URL, Tutorial, Tutorial
@section What makes Lisp different
The following sums up how bindings to foreign libraries are usually
implemented in other languages, then in Common Lisp:
@table @asis
@item Perl, Python, Java, other one-implementation languages
@cindex @acronym{SWIG}
@cindex Perl
@cindex Python
Bindings are implemented as shared objects written in C. In some
cases, the C code is generated by a tool, such as @acronym{SWIG}, but
the result is the same: a new C library that manually translates
between the language implementation's objects, such as @code{PyObject}
in Python, and whatever C object is called for, often using C
functions provided by the implementation. It also translates between
the calling conventions of the language and C.
@item Common Lisp
@cindex @acronym{SLIME}
Bindings are written in Lisp. They can be created at-will by Lisp
programs. Lisp programmers can write new bindings and add them to the
image, using a listener such as @acronym{SLIME}, as easily as with
regular Lisp definitions. The only foreign library to load is the one
being wrapped---the one with the pure C interface; no C or other
non-Lisp compilation is required.
@end table
@cindex advantages of @acronym{FFI}
@cindex benefits of @acronym{FFI}
We believe the advantages of the Common Lisp approach far outweigh any
disadvantages. Incremental development with a listener can be as
productive for C binding development as it is with other Lisp
development. Keeping it ``in the [Lisp] family'', as it were, makes
it much easier for you and other Lisp programmers to load and use the
bindings. Common Lisp implementations such as @acronym{CMUCL}, freed
from having to provide a C interface to their own objects, are thus
freed to be implemented in another language (as @acronym{CMUCL} is)
while still allowing programmers to call foreign functions.
@cindex minimal bindings
Perhaps the greatest advantage is that using an @acronym{FFI} doesn't
obligate you to become a professional binding developer. Writers of
bindings for other languages usually end up maintaining or failing to
maintain complete bindings to the foreign library. Using an
@acronym{FFI}, however, means if you only need one or two functions,
you can write bindings for only those functions, and be assured that
you can just as easily add to the bindings if need be.
@cindex C abstractions
@cindex abstractions in C
The removal of the C compiler, or C interpretation of any kind,
creates the main disadvantage: some of C's ``abstractions'' are not
available, violating information encapsulation. For example,
@code{struct}s that must be passed on the stack, or used as return
values, without corresponding functional abstractions to create and
manage the @code{struct}s, must be declared explicitly in Lisp. This
is fine for structs whose contents are ``public'', but is not so
pleasant when a struct is supposed to be ``opaque'' by convention,
even though it is not so defined.@footnote{Admittedly, this is an
advanced issue, and we encourage you to leave this text until you are
more familiar with how @cffi{} works.}
Without an abstraction to create the struct, Lisp needs to be able to
lay out the struct in memory, so must know its internal details.
@cindex workaround for C
In these cases, you can create a minimal C library to provide the
missing abstractions, without destroying all the advantages of the
Common Lisp approach discussed above. In the case of @code{struct}s,
you can write simple, pure C functions that tell you how many bytes a
struct requires or allocate new structs, read and write fields of the
struct, or whatever operations are supposed to be
public.@footnote{This does not apply to structs whose contents are
intended to be part of the public library interface. In those cases,
a pure Lisp struct definition is always preferred. In fact, many
prefer to stay in Lisp and break the encapsulation anyway, placing the
burden of correct library interface definition on the library.}
@ref{The Groveller} automates this and other processes.
Another disadvantage appears when you would rather use the foreign
language than Lisp. However, someone who prefers C to Lisp is not a
likely candidate for developing a Lisp interface to a C library.
@node Tutorial-Getting a URL, Tutorial-Loading, Tutorial-Comparison, Tutorial
@section Getting a @acronym{URL}
@cindex c@acronym{URL}
The widely available @code{libcurl} is a library for downloading files
over protocols like @acronym{HTTP}. We will use @code{libcurl} with
@cffi{} to download a web page.
Please note that there are many other ways to download files from the
web, not least the @sc{cl-curl} project to provide bindings to
@code{libcurl} via a similar @acronym{FFI}.@footnote{Specifically,
@acronym{UFFI}, an older @acronym{FFI} that takes a somewhat different
approach compared to @cffi{}. I believe that these days (December
2005) @cffi{} is more portable and actively developed, though not as
mature yet. Consensus in the free @sc{unix} Common Lisp community
seems to be that @cffi{} is preferred for new development, though
@acronym{UFFI} will likely go on for quite some time as many projects
already use it. @cffi{} includes the @code{UFFI-COMPAT} package for
complete compatibility with @acronym{UFFI}.}
@uref{http://curl.haxx.se/libcurl/c/libcurl-tutorial.html,,libcurl-tutorial(3)}
is a tutorial for @code{libcurl} programming in C. We will follow
that to develop a binding to download a file. We will also use
@file{curl.h}, @file{easy.h}, and the @command{man} pages for the
@code{libcurl} function, all available in the @samp{curl-dev} package
or equivalent for your system, or in the c@acronym{URL} source code
package. If you have the development package, the headers should be
installed in @file{/usr/include/curl/}, and the @command{man} pages
may be accessed through your favorite @command{man} facility.
@node Tutorial-Loading, Tutorial-Initializing, Tutorial-Getting a URL, Tutorial
@section Loading foreign libraries
@cindex loading @cffi{}
@cindex requiring @cffi{}
First of all, we will create a package to work in. You can save these
forms in a file, or just send them to the listener as they are. If
creating bindings for an @acronym{ASDF} package of yours, you will
want to add @code{:cffi} to the @code{:depends-on} list in your
@file{.asd} file. Otherwise, just use the @code{asdf:load-system} function to
load @cffi{}.
@tutorialsource{Initialization}
@lisp
(asdf:load-system :cffi)
;;; @lispcmt{Nothing special about the "CFFI-USER" package. We're just}
;;; @lispcmt{using it as a substitute for your own CL package.}
(defpackage :cffi-user
(:use :common-lisp :cffi))
(in-package :cffi-user)
(define-foreign-library libcurl
(:darwin (:or "libcurl.3.dylib" "libcurl.dylib"))
(:unix (:or "libcurl.so.3" "libcurl.so"))
(t (:default "libcurl")))
(use-foreign-library libcurl)
@end lisp
@cindex foreign library load
@cindex library, foreign
Using @code{define-foreign-library} and @code{use-foreign-library}, we
have loaded @code{libcurl} into Lisp, much as the linker does when you
start a C program, or @code{common-lisp:load} does with a Lisp source
file or @acronym{FASL} file. We special-cased for @sc{unix} machines
to always load a particular version, the one this tutorial was tested
with; for those who don't care, the @code{define-foreign-library}
clause @code{(t (:default "libcurl"))} should be satisfactory, and
will adapt to various operating systems.
@node Tutorial-Initializing, Tutorial-easy_setopt, Tutorial-Loading, Tutorial
@section Initializing @code{libcurl}
@cindex function definition
After the introductory matter, the tutorial goes on to present the
first function you should use.
@example
CURLcode curl_global_init(long flags);
@end example
@noindent
Let's pick this apart into appropriate Lisp code:
@tutorialsource{First CURLcode}
@lisp
;;; @lispcmt{A CURLcode is the universal error code. curl/curl.h says}
;;; @lispcmt{no return code will ever be removed, and new ones will be}
;;; @lispcmt{added to the end.}
(defctype curl-code :int)
;;; @lispcmt{Initialize libcurl with FLAGS.}
(defcfun "curl_global_init" curl-code
(flags :long))
@end lisp
@impnote{By default, CFFI assumes the UNIX viewpoint that there is one
C symbol namespace, containing all symbols in all loaded objects.
This is not so on Windows and Darwin, but we emulate UNIX's behaviour
there. @ref{defcfun} for more details.}
Note the parallels with the original C declaration. We've defined
@code{curl-code} as a wrapping type for @code{:int}; right now, it
only marks it as special, but later we will do something more
interesting with it. The point is that we don't have to do it yet.
@cindex calling foreign functions
Looking at @file{curl.h}, @code{CURL_GLOBAL_NOTHING}, a possible value
for @code{flags} above, is defined as @samp{0}. So we can now call
the function:
@example
@sc{cffi-user>} (curl-global-init 0)
@result{} 0
@end example
@cindex looks like it worked
Looking at @file{curl.h} again, @code{0} means @code{CURLE_OK}, so it
looks like the call succeeded. Note that @cffi{} converted the
function name to a Lisp-friendly name. You can specify your own name
if you want; use @code{("curl_global_init" @var{your-name-here})} as
the @var{name} argument to @code{defcfun}.
The tutorial goes on to have us allocate a handle. For good measure,
we should also include the deallocator. Let's look at these
functions:
@example
CURL *curl_easy_init( );
void curl_easy_cleanup(CURL *handle);
@end example
Advanced users may want to define special pointer types; we will
explore this possibility later. For now, just treat every pointer as
the same:
@tutorialsource{curl_easy handles}
@lisp
(defcfun "curl_easy_init" :pointer)
(defcfun "curl_easy_cleanup" :void
(easy-handle :pointer))
@end lisp
Now we can continue with the tutorial:
@example
@sc{cffi-user>} (defparameter *easy-handle* (curl-easy-init))
@result{} *EASY-HANDLE*
@sc{cffi-user>} *easy-handle*
@result{} #<FOREIGN-ADDRESS #x09844EE0>
@end example
@cindex pointers in Lisp
Note the print representation of a pointer. It changes depending on
what Lisp you are using, but that doesn't make any difference to
@cffi{}.
@node Tutorial-easy_setopt, Tutorial-Abstraction, Tutorial-Initializing, Tutorial
@section Setting download options
The @code{libcurl} tutorial says we'll want to set many options before
performing any download actions. This is done through
@code{curl_easy_setopt}:
@c That is literally ..., not an ellipsis.
@example
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
@end example
@cindex varargs
@cindex foreign arguments
We've introduced a new twist: variable arguments. There is no obvious
translation to the @code{defcfun} form, particularly as there are four
possible argument types. Because of the way C works, we could define
four wrappers around @code{curl_easy_setopt}, one for each type; in
this case, however, we'll use the general-purpose macro
@code{foreign-funcall} to call this function.
@cindex enumeration, C
To make things easier on ourselves, we'll create an enumeration of the
kinds of options we want to set. The @code{enum CURLoption} isn't the
most straightforward, but reading the @code{CINIT} C macro definition
should be enlightening.
@tutorialsource{CURLoption enumeration}
@lisp
(defmacro define-curl-options (name type-offsets &rest enum-args)
"As with CFFI:DEFCENUM, except each of ENUM-ARGS is as follows:
(NAME TYPE NUMBER)
Where the arguments are as they are with the CINIT macro defined
in curl.h, except NAME is a keyword.
TYPE-OFFSETS is a plist of TYPEs to their integer offsets, as
defined by the CURLOPTTYPE_LONG et al constants in curl.h."
(flet ((enumerated-value (type offset)
(+ (getf type-offsets type) offset)))
`(progn
(defcenum ,name
,@@(loop for (name type number) in enum-args
collect (list name (enumerated-value type number))))
',name))) ;@lispcmt{for REPL users' sanity}
(define-curl-options curl-option
(long 0 objectpoint 10000 functionpoint 20000 off-t 30000)
(:noprogress long 43)
(:nosignal long 99)
(:errorbuffer objectpoint 10)
(:url objectpoint 2))
@end lisp
With some well-placed Emacs @code{query-replace-regexp}s, you could
probably similarly define the entire @code{CURLoption} enumeration. I
have selected to transcribe a few that we will use in this tutorial.
If you're having trouble following the macrology, just macroexpand the
@code{curl-option} definition, or see the following macroexpansion,
conveniently downcased and reformatted:
@tutorialsource{DEFINE-CURL-OPTIONS macroexpansion}
@lisp
(progn
(defcenum curl-option
(:noprogress 43)
(:nosignal 99)
(:errorbuffer 10010)
(:url 10002))
'curl-option)
@end lisp
@noindent
That seems more than reasonable. You may notice that we only use the
@var{type} to compute the real enumeration offset; we will also need
the type information later.
First, however, let's make sure a simple call to the foreign function
works:
@example
@sc{cffi-user>} (foreign-funcall "curl_easy_setopt"
:pointer *easy-handle*
curl-option :nosignal :long 1 curl-code)
@result{} 0
@end example
@code{foreign-funcall}, despite its surface simplicity, can be used to
call any C function. Its first argument is a string, naming the
function to be called. Next, for each argument, we pass the name of
the C type, which is the same as in @code{defcfun}, followed by a Lisp
object representing the data to be passed as the argument. The final
argument is the return type, for which we use the @code{curl-code}
type defined earlier.
@code{defcfun} just puts a convenient fa@,cade on
@code{foreign-funcall}.@footnote{This isn't entirely true; some Lisps
don't support @code{foreign-funcall}, so @code{defcfun} is implemented
without it. @code{defcfun} may also perform optimizations that
@code{foreign-funcall} cannot.} Our earlier call to
@code{curl-global-init} could have been written as follows:
@example
@sc{cffi-user>} (foreign-funcall "curl_global_init" :long 0
curl-code)
@result{} 0
@end example
Before we continue, we will take a look at what @cffi{} can and can't
do, and why this is so.
@node Tutorial-Abstraction, Tutorial-Lisp easy_setopt, Tutorial-easy_setopt, Tutorial
@section Breaking the abstraction
@cindex breaking the abstraction
@cindex abstraction breaking
In @ref{Tutorial-Comparison,, What makes Lisp different}, we mentioned
that writing an @acronym{FFI} sometimes requires depending on
information not provided as part of the interface. The easy option
@code{CURLOPT_WRITEDATA}, which we will not provide as part of the
Lisp interface, illustrates this issue.
Strictly speaking, the @code{curl-option} enumeration is not
necessary; we could have used @code{:int 99} instead of
@code{curl-option :nosignal} in our call to @code{curl_easy_setopt}
above. We defined it anyway, in part to hide the fact that we are
breaking the abstraction that the C @code{enum} provides. If the
c@acronym{URL} developers decide to change those numbers later, we
must change the Lisp enumeration, because enumeration values are not
provided in the compiled C library, @code{libcurl.so.3}.
@cffi{} works because the most useful things in C libraries ---
non-static functions and non-static variables --- are included
accessibly in @code{libcurl.so.3}. A C compiler that violated this
would be considered a worthless compiler.
The other thing @code{define-curl-options} does is give the ``type''
of the third argument passed to @code{curl_easy_setopt}. Using this
information, we can tell that the @code{:nosignal} option should
accept a long integer argument. We can implicitly assume @code{t}
@equiv{} 1 and @code{nil} @equiv{} 0, as it is in C, which takes care
of the fact that @code{CURLOPT_NOSIGNAL} is really asking for a
boolean.
The ``type'' of @code{CURLOPT_WRITEDATA} is @code{objectpoint}.
However, it is really looking for a @code{FILE*}.
@code{CURLOPT_ERRORBUFFER} is looking for a @code{char*}, so there is
no obvious @cffi{} type but @code{:pointer}.
The first thing to note is that nowhere in the C interface includes
this information; it can only be found in the manual. We could
disjoin these clearly different types ourselves, by splitting
@code{objectpoint} into @code{filepoint} and @code{charpoint}, but we
are still breaking the abstraction, because we have to augment the
entire enumeration form with this additional
information.@footnote{Another possibility is to allow the caller to
specify the desired C type of the third argument. This is essentially
what happens in a call to the function written in C.}
@cindex streams and C
@cindex @sc{file}* and streams
The second is that the @code{CURLOPT_WRITEDATA} argument is completely
incompatible with the desired Lisp data, a
stream.@footnote{@xref{Other Kinds of Streams,,, libc, GNU C Library
Reference}, for a @acronym{GNU}-only way to extend the @code{FILE*}
type. You could use this to convert Lisp streams to the needed C
data. This would be quite involved and far outside the scope of this
tutorial.} It is probably acceptable if we are controlling every file
we might want to use as this argument, in which case we can just call
the foreign function @code{fopen}. Regardless, though, we can't write
to arbitrary streams, which is exactly what we want to do for this
application.
Finally, note that the @code{curl_easy_setopt} interface itself is a
hack, intended to work around some of the drawbacks of C. The
definition of @code{Curl_setopt}, while long, is far less cluttered
than the equivalent disjoint-function set would be; in addition,
setting a new option in an old @code{libcurl} can generate a run-time
error rather than breaking the compile. Lisp can just as concisely
generate functions as compare values, and the ``undefined function''
error is just as useful as any explicit error we could define here
might be.
@node Tutorial-Lisp easy_setopt, Tutorial-Memory, Tutorial-Abstraction, Tutorial
@section Option functions in Lisp
We could use @code{foreign-funcall} directly every time we wanted to
call @code{curl_easy_setopt}. However, we can encapsulate some of the
necessary information with the following.
@lisp
;;; @lispcmt{We will use this type later in a more creative way. For}
;;; @lispcmt{now, just consider it a marker that this isn't just any}
;;; @lispcmt{pointer.}
(defctype easy-handle :pointer)
(defmacro curl-easy-setopt (easy-handle enumerated-name
value-type new-value)
"Call `curl_easy_setopt' on EASY-HANDLE, using ENUMERATED-NAME
as the OPTION. VALUE-TYPE is the CFFI foreign type of the third
argument, and NEW-VALUE is the Lisp data to be translated to the
third argument. VALUE-TYPE is not evaluated."
`(foreign-funcall "curl_easy_setopt" easy-handle ,easy-handle
curl-option ,enumerated-name
,value-type ,new-value curl-code))
@end lisp
Now we define a function for each kind of argument that encodes the
correct @code{value-type} in the above. This can be done reasonably
in the @code{define-curl-options} macroexpansion; after all, that is
where the different options are listed!
@cindex Lispy C functions
We could make @code{cl:defun} forms in the expansion that simply call
@code{curl-easy-setopt}; however, it is probably easier and clearer to
use @code{defcfun}. @code{define-curl-options} was becoming unwieldy,
so I defined some helpers in this new definition.
@smalllisp
(defun curry-curl-option-setter (function-name option-keyword)
"Wrap the function named by FUNCTION-NAME with a version that
curries the second argument as OPTION-KEYWORD.
This function is intended for use in DEFINE-CURL-OPTION-SETTER."
(setf (symbol-function function-name)
(let ((c-function (symbol-function function-name)))
(lambda (easy-handle new-value)
(funcall c-function easy-handle option-keyword
new-value)))))
(defmacro define-curl-option-setter (name option-type
option-value foreign-type)
"Define (with DEFCFUN) a function NAME that calls
curl_easy_setopt. OPTION-TYPE and OPTION-VALUE are the CFFI
foreign type and value to be passed as the second argument to
easy_setopt, and FOREIGN-TYPE is the CFFI foreign type to be used
for the resultant function's third argument.
This macro is intended for use in DEFINE-CURL-OPTIONS."
`(progn
(defcfun ("curl_easy_setopt" ,name) curl-code
(easy-handle easy-handle)
(option ,option-type)
(new-value ,foreign-type))
(curry-curl-option-setter ',name ',option-value)))
(defmacro define-curl-options (type-name type-offsets &rest enum-args)
"As with CFFI:DEFCENUM, except each of ENUM-ARGS is as follows:
(NAME TYPE NUMBER)
Where the arguments are as they are with the CINIT macro defined
in curl.h, except NAME is a keyword.
TYPE-OFFSETS is a plist of TYPEs to their integer offsets, as
defined by the CURLOPTTYPE_LONG et al constants in curl.h.
Also, define functions for each option named
set-`TYPE-NAME'-`OPTION-NAME', where OPTION-NAME is the NAME from
the above destructuring."
(flet ((enumerated-value (type offset)
(+ (getf type-offsets type) offset))
;; @lispcmt{map PROCEDURE, destructuring each of ENUM-ARGS}
(map-enum-args (procedure)
(mapcar (lambda (arg) (apply procedure arg)) enum-args))
;; @lispcmt{build a name like SET-CURL-OPTION-NOSIGNAL}
(make-setter-name (option-name)
(intern (concatenate
'string "SET-" (symbol-name type-name)
"-" (symbol-name option-name)))))
`(progn
(defcenum ,type-name
,@@(map-enum-args
(lambda (name type number)
(list name (enumerated-value type number)))))
,@@(map-enum-args
(lambda (name type number)
(declare (ignore number))
`(define-curl-option-setter ,(make-setter-name name)
,type-name ,name ,(ecase type
(long :long)
(objectpoint :pointer)
(functionpoint :pointer)
(off-t :long)))))
',type-name)))
@end smalllisp
@noindent
Macroexpanding our @code{define-curl-options} form once more, we
see something different:
@lisp
(progn
(defcenum curl-option
(:noprogress 43)
(:nosignal 99)
(:errorbuffer 10010)
(:url 10002))
(define-curl-option-setter set-curl-option-noprogress
curl-option :noprogress :long)
(define-curl-option-setter set-curl-option-nosignal
curl-option :nosignal :long)
(define-curl-option-setter set-curl-option-errorbuffer
curl-option :errorbuffer :pointer)
(define-curl-option-setter set-curl-option-url
curl-option :url :pointer)
'curl-option)
@end lisp
@noindent
Macroexpanding one of the new @code{define-curl-option-setter}
forms yields the following:
@lisp
(progn
(defcfun ("curl_easy_setopt" set-curl-option-nosignal) curl-code
(easy-handle easy-handle)
(option curl-option)
(new-value :long))
(curry-curl-option-setter 'set-curl-option-nosignal ':nosignal))
@end lisp
@noindent
Finally, let's try this out:
@example
@sc{cffi-user>} (set-curl-option-nosignal *easy-handle* 1)
@result{} 0
@end example
@noindent
Looks like it works just as well. This interface is now reasonably
high-level to wash out some of the ugliness of the thinnest possible
@code{curl_easy_setopt} @acronym{FFI}, without obscuring the remaining
C bookkeeping details we will explore.
@node Tutorial-Memory, Tutorial-Callbacks, Tutorial-Lisp easy_setopt, Tutorial
@section Memory management
According to the documentation for @code{curl_easy_setopt}, the type
of the third argument when @var{option} is @code{CURLOPT_ERRORBUFFER}
is @code{char*}. Above, we've defined
@code{set-curl-option-errorbuffer} to accept a @code{:pointer} as the
new option value. However, there is a @cffi{} type @code{:string},
which translates Lisp strings to C strings when passed as arguments to
foreign function calls. Why not, then, use @code{:string} as the
@cffi{} type of the third argument? There are two reasons, both
related to the necessity of breaking abstraction described in
@ref{Tutorial-Abstraction,, Breaking the abstraction}.
The first reason also applies to @code{CURLOPT_URL}, which we will use
to illustrate the point. Assuming we have changed the type of the
third argument underlying @code{set-curl-option-url} to
@code{:string}, look at these two equivalent forms.
@lisp
(set-curl-option-url *easy-handle* "http://www.cliki.net/CFFI")
@equiv{} (with-foreign-string (url "http://www.cliki.net/CFFI")
(foreign-funcall "curl_easy_setopt" easy-handle *easy-handle*
curl-option :url :pointer url curl-code))
@end lisp
@noindent
The latter, in fact, is mostly equivalent to what a foreign function
call's macroexpansion actually does. As you can see, the Lisp string
@code{"@clikicffi{}"} is copied into a @code{char} array and
null-terminated; the pointer to beginning of this array, now a C
string, is passed as a @cffi{} @code{:pointer} to the foreign
function.
@cindex dynamic extent
@cindex foreign values with dynamic extent
Unfortunately, the C abstraction has failed us, and we must break it.
While @code{:string} works well for many @code{char*} arguments, it
does not for cases like this. As the @code{curl_easy_setopt}
documentation explains, ``The string must remain present until curl no
longer needs it, as it doesn't copy the string.'' The C string
created by @code{with-foreign-string}, however, only has dynamic
extent: it is ``deallocated'' when the body (above containing the
@code{foreign-funcall} form) exits.
@cindex premature deallocation
If we are supposed to keep the C string around, but it goes away, what
happens when some @code{libcurl} function tries to access the
@acronym{URL} string? We have reentered the dreaded world of C
``undefined behavior''. In some Lisps, it will probably get a chunk
of the Lisp/C stack. You may segfault. You may get some random piece
of other data from the heap. Maybe, in a world where ``dynamic
extent'' is defined to be ``infinite extent'', everything will turn
out fine. Regardless, results are likely to be almost universally
unpleasant.@footnote{``@i{But I thought Lisp was supposed to protect
me from all that buggy C crap!}'' Before asking a question like that,
remember that you are a stranger in a foreign land, whose residents
have a completely different set of values.}
Returning to the current @code{set-curl-option-url} interface, here is
what we must do:
@lisp
(let (easy-handle)
(unwind-protect
(with-foreign-string (url "http://www.cliki.net/CFFI")
(setf easy-handle (curl-easy-init))
(set-curl-option-url easy-handle url)
#|@lispcmt{do more with the easy-handle, like actually get the URL}|#)
(when easy-handle
(curl-easy-cleanup easy-handle))))
@end lisp
@c old comment to luis: I go on to say that this isn't obviously
@c extensible to new option settings that require C strings to stick
@c around, as it would involve re-evaluating the unwind-protect form
@c with more dynamic memory allocation. So I plan to show how to
@c write something similar to ObjC's NSAutoreleasePool, to be managed
@c with a simple unwind-protect form.
@noindent
That is fine for the single string defined here, but for every string
option we want to pass, we have to surround the body of
@code{with-foreign-string} with another @code{with-foreign-string}
wrapper, or else do some extremely error-prone pointer manipulation
and size calculation in advance. We could alleviate some of the pain
with a recursively expanding macro, but this would not remove the need
to modify the block every time we want to add an option, anathema as
it is to a modular interface.
Before modifying the code to account for this case, consider the other
reason we can't simply use @code{:string} as the foreign type. In C,
a @code{char *} is a @code{char *}, not necessarily a string. The
option @code{CURLOPT_ERRORBUFFER} accepts a @code{char *}, but does
not expect anything about the data there. However, it does expect
that some @code{libcurl} function we call later can write a C string
of up to 255 characters there. We, the callers of the function, are
expected to read the C string at a later time, exactly the opposite of
what @code{:string} implies.
With the semantics for an input string in mind --- namely, that the
string should be kept around until we @code{curl_easy_cleanup} the
easy handle --- we are ready to extend the Lisp interface:
@lisp
(defvar *easy-handle-cstrings* (make-hash-table)
"Hashtable of easy handles to lists of C strings that may be
safely freed after the handle is freed.")
(defun make-easy-handle ()
"Answer a new CURL easy interface handle, to which the lifetime
of C strings may be tied. See `add-curl-handle-cstring'."
(let ((easy-handle (curl-easy-init)))
(setf (gethash easy-handle *easy-handle-cstrings*) '())
easy-handle))
(defun free-easy-handle (handle)
"Free CURL easy interface HANDLE and any C strings created to
be its options."
(curl-easy-cleanup handle)
(mapc #'foreign-string-free
(gethash handle *easy-handle-cstrings*))
(remhash handle *easy-handle-cstrings*))
(defun add-curl-handle-cstring (handle cstring)
"Add CSTRING to be freed when HANDLE is, answering CSTRING."
(car (push cstring (gethash handle *easy-handle-cstrings*))))
@end lisp
@noindent
Here we have redefined the interface to create and free handles, to
associate a list of allocated C strings with each handle while it
exists. The strategy of using different function names to wrap around
simple foreign functions is more common than the solution implemented
earlier with @code{curry-curl-option-setter}, which was to modify the
function name's function slot.@footnote{There are advantages and
disadvantages to each approach; I chose to @code{(setf
symbol-function)} earlier because it entailed generating fewer magic
function names.}
Incidentally, the next step is to redefine
@code{curry-curl-option-setter} to allocate C strings for the
appropriate length of time, given a Lisp string as the
@code{new-value} argument:
@lisp
(defun curry-curl-option-setter (function-name option-keyword)
"Wrap the function named by FUNCTION-NAME with a version that
curries the second argument as OPTION-KEYWORD.
This function is intended for use in DEFINE-CURL-OPTION-SETTER."
(setf (symbol-function function-name)
(let ((c-function (symbol-function function-name)))
(lambda (easy-handle new-value)
(funcall c-function easy-handle option-keyword
(if (stringp new-value)
(add-curl-handle-cstring
easy-handle
(foreign-string-alloc new-value))
new-value))))))
@end lisp
@noindent
A quick analysis of the code shows that you need only reevaluate the
@code{curl-option} enumeration definition to take advantage of these
new semantics. Now, for good measure, let's reallocate the handle
with the new functions we just defined, and set its @acronym{URL}:
@example
@sc{cffi-user>} (curl-easy-cleanup *easy-handle*)
@result{} NIL
@sc{cffi-user>} (setf *easy-handle* (make-easy-handle))
@result{} #<FOREIGN-ADDRESS #x09844EE0>
@sc{cffi-user>} (set-curl-option-nosignal *easy-handle* 1)
@result{} 0
@sc{cffi-user>} (set-curl-option-url *easy-handle*
"http://www.cliki.net/CFFI")
@result{} 0
@end example
@cindex strings
For fun, let's inspect the Lisp value of the C string that was created
to hold @code{"@clikicffi{}"}. By virtue of the implementation of
@code{add-curl-handle-cstring}, it should be accessible through the
hash table defined:
@example
@sc{cffi-user>} (foreign-string-to-lisp
(car (gethash *easy-handle* *easy-handle-cstrings*)))
@result{} "http://www.cliki.net/CFFI"
@end example
@noindent
Looks like that worked, and @code{libcurl} now knows what
@acronym{URL} we want to retrieve.
Finally, we turn back to the @code{:errorbuffer} option mentioned at
the beginning of this section. Whereas the abstraction added to
support string inputs works fine for cases like @code{CURLOPT_URL}, it
hides the detail of keeping the C string; for @code{:errorbuffer},
however, we need that C string.
In a moment, we'll define something slightly cleaner, but for now,
remember that you can always hack around anything. We're modifying
handle creation, so make sure you free the old handle before
redefining @code{free-easy-handle}.
@smalllisp
(defvar *easy-handle-errorbuffers* (make-hash-table)
"Hashtable of easy handles to C strings serving as error
writeback buffers.")
;;; @lispcmt{An extra byte is very little to pay for peace of mind.}
(defparameter *curl-error-size* 257
"Minimum char[] size used by cURL to report errors.")
(defun make-easy-handle ()
"Answer a new CURL easy interface handle, to which the lifetime
of C strings may be tied. See `add-curl-handle-cstring'."
(let ((easy-handle (curl-easy-init)))
(setf (gethash easy-handle *easy-handle-cstrings*) '())
(setf (gethash easy-handle *easy-handle-errorbuffers*)
(foreign-alloc :char :count *curl-error-size*
:initial-element 0))
easy-handle))
(defun free-easy-handle (handle)
"Free CURL easy interface HANDLE and any C strings created to
be its options."
(curl-easy-cleanup handle)
(foreign-free (gethash handle *easy-handle-errorbuffers*))
(remhash handle *easy-handle-errorbuffers*)
(mapc #'foreign-string-free
(gethash handle *easy-handle-cstrings*))
(remhash handle *easy-handle-cstrings*))
(defun get-easy-handle-error (handle)
"Answer a string containing HANDLE's current error message."
(foreign-string-to-lisp
(gethash handle *easy-handle-errorbuffers*)))
@end smalllisp
Be sure to once again set the options we've set thus far. You may
wish to define yet another wrapper function to do this.
@node Tutorial-Callbacks, Tutorial-Completion, Tutorial-Memory, Tutorial
@section Calling Lisp from C
If you have been reading
@uref{http://curl.haxx.se/libcurl/c/curl_easy_setopt.html,,
@code{curl_easy_setopt(3)}}, you should have noticed that some options
accept a function pointer. In particular, we need one function
pointer to set as @code{CURLOPT_WRITEFUNCTION}, to be called by
@code{libcurl} rather than the reverse, in order to receive data as it
is downloaded.
A binding writer without the aid of @acronym{FFI} usually approaches
this problem by writing a C function that accepts C data, converts to
the language's internal objects, and calls the callback provided by
the user, again in a reverse of usual practices.
The @cffi{} approach to callbacks precisely mirrors its differences
with the non-@acronym{FFI} approach on the ``calling C from Lisp''
side, which we have dealt with exclusively up to now. That is, you
define a callback function in Lisp using @code{defcallback}, and
@cffi{} effectively creates a C function to be passed as a function
pointer.
@impnote{This is much trickier than calling C functions from Lisp, as
it literally involves somehow generating a new C function that is as
good as any created by the compiler. Therefore, not all Lisps support
them. @xref{Implementation Support}, for information about @cffi{}
support issues in this and other areas. You may want to consider
changing to a Lisp that supports callbacks in order to continue with
this tutorial.}
@cindex callback definition
@cindex defining callbacks
Defining a callback is very similar to defining a callout; the main
difference is that we must provide some Lisp forms to be evaluated as
part of the callback. Here is the signature for the function the
@code{:writefunction} option takes:
@example
size_t
@var{function}(void *ptr, size_t size, size_t nmemb, void *stream);
@end example
@impnote{size_t is almost always an unsigned int. You can get this
and many other types using feature tests for your system by using
cffi-grovel.}
The above signature trivially translates into a @cffi{}
@code{defcallback} form, as follows.
@lisp
;;; @lispcmt{Alias in case size_t changes.}
(defctype size :unsigned-int)
;;; @lispcmt{To be set as the CURLOPT_WRITEFUNCTION of every easy handle.}
(defcallback easy-write size ((ptr :pointer) (size size)
(nmemb size) (stream :pointer))
(let ((data-size (* size nmemb)))
(handler-case
;; @lispcmt{We use the dynamically-bound *easy-write-procedure* to}
;; @lispcmt{call a closure with useful lexical context.}
(progn (funcall (symbol-value '*easy-write-procedure*)
(foreign-string-to-lisp ptr :count data-size))
data-size) ;@lispcmt{indicates success}
;; @lispcmt{The WRITEFUNCTION should return something other than the}
;; @lispcmt{#bytes available to signal an error.}
(error () (if (zerop data-size) 1 0)))))
@end lisp
First, note the correlation of the first few forms, used to declare
the C function's signature, with the signature in C syntax. We
provide a Lisp name for the function, its return type, and a name and
type for each argument.
In the body, we call the dynamically-bound
@code{*easy-write-procedure*} with a ``finished'' translation, of
pulling together the raw data and size into a Lisp string, rather than
deal with the data directly. As part of calling
@code{curl_easy_perform} later, we'll bind that variable to a closure
with more useful lexical bindings than the top-level
@code{defcallback} form.
Finally, we make a halfhearted effort to prevent non-local exits from
unwinding the C stack, covering the most likely case with an
@code{error} handler, which is usually triggered
unexpectedly.@footnote{Unfortunately, we can't protect against
@emph{all} non-local exits, such as @code{return}s and @code{throw}s,
because @code{unwind-protect} cannot be used to ``short-circuit'' a
non-local exit in Common Lisp, due to proposal @code{minimal} in
@uref{http://www.lisp.org/HyperSpec/Issues/iss152-writeup.html,
@acronym{ANSI} issue @sc{Exit-Extent}}. Furthermore, binding an
@code{error} handler prevents higher-up code from invoking restarts
that may be provided under the callback's dynamic context. Such is
the way of compromise.} The reason is that most C code is written to
understand its own idiosyncratic error condition, implemented above in
the case of @code{curl_easy_perform}, and more ``undefined behavior''
can result if we just wipe C stack frames without allowing them to
execute whatever cleanup actions as they like.
Using the @code{CURLoption} enumeration in @file{curl.h} once more, we
can describe the new option by modifying and reevaluating
@code{define-curl-options}.
@lisp
(define-curl-options curl-option
(long 0 objectpoint 10000 functionpoint 20000 off-t 30000)
(:noprogress long 43)
(:nosignal long 99)
(:errorbuffer objectpoint 10)
(:url objectpoint 2)
(:writefunction functionpoint 11)) ;@lispcmt{new item here}
@end lisp
Finally, we can use the defined callback and the new
@code{set-curl-option-writefunction} to finish configuring the easy
handle, using the @code{callback} macro to retrieve a @cffi{}
@code{:pointer}, which works like a function pointer in C code.
@example
@sc{cffi-user>} (set-curl-option-writefunction
*easy-handle* (callback easy-write))
@result{} 0
@end example
@node Tutorial-Completion, Tutorial-Types, Tutorial-Callbacks, Tutorial
@section A complete @acronym{FFI}?
@c TeX goes insane on @uref{@clikicffi{}}
With all options finally set and a medium-level interface developed,
we can finish the definition and retrieve
@uref{http://www.cliki.net/CFFI}, as is done in the tutorial.
@lisp
(defcfun "curl_easy_perform" curl-code
(handle easy-handle))
@end lisp
@example
@sc{cffi-user>} (with-output-to-string (contents)
(let ((*easy-write-procedure*
(lambda (string)
(write-string string contents))))
(declare (special *easy-write-procedure*))
(curl-easy-perform *easy-handle*)))
@result{} "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"
@enddots{}
Now fear, comprehensively</P>
"
@end example
Of course, that itself is slightly unwieldy, so you may want to define
a function around it that simply retrieves a @acronym{URL}. I will
leave synthesis of all the relevant @acronym{REPL} forms presented
thus far into a single function as an exercise for the reader.
The remaining sections of this tutorial explore some advanced features
of @cffi{}; the definition of new types will receive special
attention. Some of these features are essential for particular
foreign function calls; some are very helpful when trying to develop a
Lispy interface to C.
@node Tutorial-Types, Tutorial-Conclusion, Tutorial-Completion, Tutorial
@section Defining new types
We've occasionally used the @code{defctype} macro in previous sections
as a kind of documentation, much what you'd use @code{typedef} for in
C. We also tried one special kind of type definition, the
@code{defcenum} type. @xref{defcstruct}, for a definition macro that
may come in handy if you need to use C @code{struct}s as data.
@cindex type definition
@cindex data in Lisp and C
@cindex translating types
However, all of these are mostly sugar for the powerful underlying
foreign type interface called @dfn{type translators}. You can easily
define new translators for any simple named foreign type. Since we've
defined the new type @code{curl-code} to use as the return type for
various @code{libcurl} functions, we can use that to directly convert
c@acronym{URL} errors to Lisp errors.
@code{defctype}'s purpose is to define simple @code{typedef}-like
aliases. In order to use @dfn{type translators} we must use the
@code{define-foreign-type} macro. So let's redefine @code{curl-code}
using it.
@lisp
(define-foreign-type curl-code-type ()
()
(:actual-type :int)
(:simple-parser curl-code))
@end lisp
@code{define-foreign-type} is a thin wrapper around @code{defclass}.
For now, all you need to know in the context of this example is that
it does what @code{(defctype curl-code :int)} would do and,
additionally, defines a new class @code{curl-code-type} which we will
take advantage of shortly.
The @code{CURLcode} enumeration seems to follow the typical error code
convention of @samp{0} meaning all is well, and each non-zero integer
indicating a different kind of error. We can apply that trivially to
differentiate between normal exits and error exits.
@lisp
(define-condition curl-code-error (error)
(($code :initarg :curl-code :reader curl-error-code))
(:report (lambda (c stream)
(format stream "libcurl function returned error ~A"
(curl-error-code c))))
(:documentation "Signalled when a libcurl function answers
a code other than CURLE_OK."))
(defmethod translate-from-foreign (value (type curl-code-type))
"Raise a CURL-CODE-ERROR if VALUE, a curl-code, is non-zero."
(if (zerop value)
:curle-ok
(error 'curl-code-error :curl-code value)))
@end lisp
@noindent
The heart of this translator is new method
@code{translate-from-foreign}. By specializing the @var{type}
parameter on @code{curl-code-type}, we immediately modify the behavior
of every function that returns a @code{curl-code} to pass the result
through this new method.
To see the translator in action, try invoking a function that returns
a @code{curl-code}. You need to reevaluate the respective
@code{defcfun} form so that it picks up the new @code{curl-code}
definition.
@example
@sc{cffi-user>} (set-curl-option-nosignal *easy-handle* 1)
@result{} :CURLE-OK
@end example
@noindent
As the result was @samp{0}, the new method returned @code{:curle-ok},
just as specified.@footnote{It might be better to return
@code{(values)} than @code{:curle-ok} in real code, but this is good
for illustration.} I will leave disjoining the separate
@code{CURLcode}s into condition types and improving the @code{:report}
function as an exercise for you.
The creation of @code{*easy-handle-cstrings*} and
@code{*easy-handle-errorbuffers*} as properties of @code{easy-handle}s
is a kluge. What we really want is a Lisp structure that stores these
properties along with the C pointer. Unfortunately,
@code{easy-handle} is currently just a fancy name for the foreign type
@code{:pointer}; the actual pointer object varies from Common Lisp
implementation to implementation, needing only to satisfy
@code{pointerp} and be returned from @code{make-pointer} and friends.
One solution that would allow us to define a new Lisp structure to
represent @code{easy-handle}s would be to write a wrapper around every
function that currently takes an @code{easy-handle}; the wrapper would
extract the pointer and pass it to the foreign function. However, we
can use type translators to more elegantly integrate this
``translation'' into the foreign function calling framework, using
@code{translate-to-foreign}.
@smalllisp
(defclass easy-handle ()
((pointer :initform (curl-easy-init)
:documentation "Foreign pointer from curl_easy_init")
(error-buffer
:initform (foreign-alloc :char :count *curl-error-size*
:initial-element 0)
:documentation "C string describing last error")
(c-strings :initform '()
:documentation "C strings set as options"))
(:documentation "I am a parameterization you may pass to
curl-easy-perform to perform a cURL network protocol request."))
(defmethod initialize-instance :after ((self easy-handle) &key)
(set-curl-option-errorbuffer self (slot-value self 'error-buffer)))
(defun add-curl-handle-cstring (handle cstring)
"Add CSTRING to be freed when HANDLE is, answering CSTRING."
(car (push cstring (slot-value handle 'c-strings))))
(defun get-easy-handle-error (handle)
"Answer a string containing HANDLE's current error message."
(foreign-string-to-lisp
(slot-value handle 'error-buffer)))
(defun free-easy-handle (handle)
"Free CURL easy interface HANDLE and any C strings created to
be its options."
(with-slots (pointer error-buffer c-strings) handle
(curl-easy-cleanup pointer)
(foreign-free error-buffer)
(mapc #'foreign-string-free c-strings)))
(define-foreign-type easy-handle-type ()
()
(:actual-type :pointer)
(:simple-parser easy-handle))
(defmethod translate-to-foreign (handle (type easy-handle-type))
"Extract the pointer from an easy-HANDLE."
(slot-value handle 'pointer))
@end smalllisp
While we changed some of the Lisp functions defined earlier to use
@acronym{CLOS} slots rather than hash tables, the foreign functions
work just as well as they did before.
@cindex limitations of type translators
The greatest strength, and the greatest limitation, of the type
translator comes from its generalized interface. As stated
previously, we could define all foreign function calls in terms of the
primitive foreign types provided by @cffi{}. The type translator
interface allows us to cleanly specify the relationship between Lisp
and C data, independent of where it appears in a function call. This
independence comes at a price; for example, it cannot be used to
modify translation semantics based on other arguments to a function
call. In these cases, you should rely on other features of Lisp,
rather than the powerful, yet domain-specific, type translator
interface.
@node Tutorial-Conclusion, , Tutorial-Types, Tutorial
@section What's next?
@cffi{} provides a rich and powerful foundation for communicating with
foreign libraries; as we have seen, it is up to you to make that
experience a pleasantly Lispy one. This tutorial does not cover all
the features of @cffi{}; please see the rest of the manual for
details. In particular, if something seems obviously missing, it is
likely that either code or a good reason for lack of code is already
present.
@impnote{There are some other things in @cffi{} that might deserve
tutorial sections, such as free-translated-object, or structs. Let us
know which ones you care about.}
@c ===================================================================
@c CHAPTER: Wrapper generators
@node Wrapper generators, Foreign Types, Tutorial, Top
@chapter Wrapper generators
@cffi{}'s interface is designed for human programmers, being aimed at
aesthetic as well as technical sophistication. However, there are a
few programs aimed at translating C and C++ header files, or
approximations thereof, into @cffi{} forms constituting a foreign
interface to the symbols in those files.
These wrapper generators are known to support output of @cffi{} forms.
@table @asis
@item @uref{http://www.cliki.net/Verrazano,Verrazano}
Designed specifically for Common Lisp. Uses @acronym{GCC}'s parser
output in @acronym{XML} format to discover functions, variables, and
other header file data. This means you need @acronym{GCC} to generate
forms; on the other hand, the parser employed is mostly compliant with
@acronym{ANSI} C.
@item @uref{http://www.cliki.net/SWIG,SWIG}
A foreign interface generator originally designed to generate Python
bindings, it has been ported to many other systems, including @cffi{}
in version 1.3.28. Includes its own C declaration munger, not
intended to be fully-compliant with @acronym{ANSI} C.
@end table
First, this manual does not describe use of these other programs; they
have documentation of their own. If you have problems using a
generated interface, please look at the output @cffi{} forms and
verify that they are a correct @cffi{} interface to the library in
question; if they are correct, contact @cffi{} developers with
details, keeping in mind that they communicate in terms of those forms
rather than any particular wrapper generator. Otherwise, contact the
maintainers of the wrapper generator you are using, provided you can
reasonably expect more accuracy from the generator.
When is more accuracy an unreasonable expectation? As described in
the tutorial (@pxref{Tutorial-Abstraction,, Breaking the
abstraction}), the information in C declarations is insufficient to
completely describe every interface. In fact, it is quite common to
run into an interface that cannot be handled automatically, and
generators should be excused from generating a complete interface in
these cases.
As further described in the tutorial, the thinnest Lisp interface to a
C function is not always the most pleasant one. In many cases, you
will want to manually write a Lispier interface to the C functions
that interest you.
Wrapper generators should be treated as time-savers, not complete
automation of the full foreign interface writing job. Reports of the
amount of work done by generators vary from 30% to 90%. The
incremental development style enabled by @cffi{} generally reduces
this proportion below that for languages like Python.
@c Where I got the above 30-90% figures:
@c 30%: lemonodor's post about SWIG
@c 90%: Balooga on #lisp. He said 99%, but that's probably an
@c exaggeration (leave it to me to pass judgement :)
@c -stephen
@c ===================================================================
@c CHAPTER: Foreign Types
@node Foreign Types, Pointers, Wrapper generators, Top
@chapter Foreign Types
Foreign types describe how data is translated back and forth between C
and Lisp. @cffi{} provides various built-in types and allows the user to
define new types.
@menu
* Built-In Types::
* Other Types::
* Defining Foreign Types::
* Foreign Type Translators::
* Optimizing Type Translators::
* Foreign Structure Types::
* Allocating Foreign Objects::
Dictionary
* convert-from-foreign::
* convert-to-foreign::
* defbitfield::
* defcstruct::
* defcunion::
* defctype::
* defcenum::
@c * define-type-spec-parser::
* define-foreign-type::
* define-parse-method::
@c * explain-foreign-slot-value:
* foreign-bitfield-symbols::
* foreign-bitfield-value::
* foreign-enum-keyword::
* foreign-enum-value::
* foreign-slot-names::
* foreign-slot-offset::
* foreign-slot-pointer::
* foreign-slot-value::
* foreign-type-alignment::
* foreign-type-size::
* free-converted-object::
* free-translated-object::
* translate-from-foreign::
* translate-to-foreign::
* translate-into-foreign-memory::
* with-foreign-slots::
@end menu
@node Built-In Types, Other Types, Foreign Types, Foreign Types
@section Built-In Types
@ForeignType{:char}
@ForeignType{:unsigned-char}
@ForeignType{:short}
@ForeignType{:unsigned-short}
@ForeignType{:int}
@ForeignType{:unsigned-int}
@ForeignType{:long}
@ForeignType{:unsigned-long}
@ForeignType{:long-long}
@ForeignType{:unsigned-long-long}
These types correspond to the native C integer types according to the
@acronym{ABI} of the Lisp implementation's host system.
@code{:long-long} and @code{:unsigned-long-long} are not supported
natively on all implementations. However, they are emulated by
@code{mem-ref} and @code{mem-set}.
When those types are @strong{not} available, the symbol
@code{cffi-sys::no-long-long} is pushed into @code{*features*}.
@ForeignType{:uchar}
@ForeignType{:ushort}
@ForeignType{:uint}
@ForeignType{:ulong}
@ForeignType{:llong}
@ForeignType{:ullong}
For convenience, the above types are provided as shortcuts for
@code{unsigned-char}, @code{unsigned-short}, @code{unsigned-int},
@code{unsigned-long}, @code{long-long} and @code{unsigned-long-long},
respectively.
@ForeignType{:int8}
@ForeignType{:uint8}
@ForeignType{:int16}
@ForeignType{:uint16}
@ForeignType{:int32}
@ForeignType{:uint32}
@ForeignType{:int64}
@ForeignType{:uint64}
Foreign integer types of specific sizes, corresponding to the C types
defined in @code{stdint.h}.
@c @ForeignType{:size}
@c @ForeignType{:ssize}
@c @ForeignType{:ptrdiff}
@c @ForeignType{:time}
@c Foreign integer types corresponding to the standard C types (without
@c the @code{_t} suffix).
@c @impnote{These are not implemented yet. --luis}
@c @impnote{I'm sure there are more of these that could be useful, let's
@c add any types that can't be defined portably to this list as
@c necessary. --james}
@ForeignType{:float}
@ForeignType{:double}
On all systems, the @code{:float} and @code{:double} types represent a
C @code{float} and @code{double}, respectively. On most but not all
systems, @code{:float} and @code{:double} represent a Lisp
@code{single-float} and @code{double-float}, respectively. It is not
so useful to consider the relationship between Lisp types and C types
as isomorphic, as simply to recognize the relationship, and relative
precision, among each respective category.
@ForeignType{:long-double}
This type is only supported on SCL.
@ForeignType{:pointer &optional type}
A foreign pointer to an object of any type, corresponding to
@code{void *}. You can optionally specify type of pointer
(e.g. @code{(:pointer :char)}). Although @cffi{} won't do anything
with that information yet, it is useful for documentation purposes.
@ForeignType{:void}
No type at all. Only valid as the return type of a function.
@node Other Types, Defining Foreign Types, Built-In Types, Foreign Types
@section Other Types
@cffi{} also provides a few useful types that aren't built-in C
types.
@ForeignType{:string}
The @code{:string} type performs automatic conversion between Lisp and
C strings. Note that, in the case of functions the converted C string
will have dynamic extent (i.e.@: it will be automatically freed after
the foreign function returns).
In addition to Lisp strings, this type will accept foreign pointers
and pass them unmodified.
A method for @ref{free-translated-object} is specialized for this
type. So, for example, foreign strings allocated by this type and
passed to a foreign function will be freed after the function
returns.
@lisp
CFFI> (foreign-funcall "getenv" :string "SHELL" :string)
@result{} "/bin/bash"
CFFI> (with-foreign-string (str "abcdef")
(foreign-funcall "strlen" :string str :int))
@result{} 6
@end lisp
@ForeignType{:string+ptr}
Like @code{:string} but returns a list with two values when convert
from C to Lisp: a Lisp string and the C string's foreign pointer.
@lisp
CFFI> (foreign-funcall "getenv" :string "SHELL" :string+ptr)
@result{} ("/bin/bash" #.(SB-SYS:INT-SAP #XBFFFFC6F))
@end lisp
@ForeignType{:boolean &optional (base-type :int)}
The @code{:boolean} type converts between a Lisp boolean and a C
boolean. It canonicalizes to @var{base-type} which is @code{:int} by
default.
@lisp
(convert-to-foreign nil :boolean) @result{} 0
(convert-to-foreign t :boolean) @result{} 1
(convert-from-foreign 0 :boolean) @result{} nil
(convert-from-foreign 1 :boolean) @result{} t
@end lisp
@ForeignType{:bool}
The @code{:bool} type represents the C99 @code{_Bool} or C++
@code{bool}. Its size is usually 1 byte except on OSX where it's an
@code{int}.
@ForeignType{:wrapper base-type &key to-c from-c}
The @code{:wrapper} type stores two symbols passed to the @var{to-c}
and @var{from-c} arguments. When a value is being translated to or
from C, this type @code{funcall}s the respective symbol.
@code{:wrapper} types will be typedefs for @var{base-type} and will
inherit its translators, if any.
Here's an example of how the @code{:boolean} type could be defined in
terms of @code{:wrapper}.
@lisp
(defun bool-c-to-lisp (value)
(not (zerop value)))
(defun bool-lisp-to-c (value)
(if value 1 0))
(defctype my-bool (:wrapper :int :from-c bool-c-to-lisp
:to-c bool-lisp-to-c))
(convert-to-foreign nil 'my-bool) @result{} 0
(convert-from-foreign 1 'my-bool) @result{} t
@end lisp
@node Defining Foreign Types, Foreign Type Translators, Other Types, Foreign Types
@section Defining Foreign Types
You can define simple C-like @code{typedef}s through the
@code{defctype} macro. Defining a typedef is as simple as giving
@code{defctype} a new name and the name of the type to be wrapped.
@lisp
;;; @lispcmt{Define MY-INT as an alias for the built-in type :INT.}
(defctype my-int :int)
@end lisp
With this type definition, one can, for instance, declare arguments to
foreign functions as having the type @code{my-int}, and they will be
passed as integers.
@subheading More complex types
@cffi{} offers another way to define types through
@code{define-foreign-type}, a thin wrapper macro around
@code{defclass}. As an example, let's go through the steps needed to
define a @code{(my-string &key encoding)} type. First, we need to
define our type class:
@lisp
(define-foreign-type my-string-type ()
((encoding :reader string-type-encoding :initarg :encoding))
(:actual-type :pointer))
@end lisp
The @code{:actual-type} class option tells CFFI that this type will
ultimately be passed to and received from foreign code as a
@code{:pointer}. Now you need to tell CFFI how to parse a type
specification such as @code{(my-string :encoding :utf8)} into an
instance of @code{my-string-type}. We do that with
@code{define-parse-method}:
@lisp
(define-parse-method my-string (&key (encoding :utf-8))
(make-instance 'my-string-type :encoding encoding))
@end lisp
The next section describes how make this type actually translate
between C and Lisp strings.
@node Foreign Type Translators, Optimizing Type Translators, Defining Foreign Types, Foreign Types
@section Foreign Type Translators
Type translators are used to automatically convert Lisp values to or
from foreign values. For example, using type translators, one can
take the @code{my-string} type defined in the previous section and
specify that it should:
@itemize
@item
convert C strings to Lisp strings;
@item
convert Lisp strings to newly allocated C strings;
@item
free said C strings when they are no longer needed.
@end itemize
In order to tell @cffi{} how to automatically convert Lisp values to
foreign values, define a specialized method for the
@code{translate-to-foreign} generic function:
@lisp
;;; @lispcmt{Define a method that converts Lisp strings to C strings.}
(defmethod translate-to-foreign (string (type my-string-type))
(foreign-string-alloc string :encoding (string-type-encoding type)))
@end lisp
@noindent
From now on, whenever an object is passed as a @code{my-string} to a
foreign function, this method will be invoked to convert the Lisp
value. To perform the inverse operation, which is needed for functions
that return a @code{my-string}, specialize the
@code{translate-from-foreign} generic function in the same manner:
@lisp
;;; @lispcmt{Define a method that converts C strings to Lisp strings.}
(defmethod translate-from-foreign (pointer (type my-string-type))
(foreign-string-to-lisp pointer :encoding (string-type-encoding type)))
@end lisp
@noindent
When a @code{translate-to-foreign} method requires allocation of
foreign memory, you must also define a @code{free-translated-object}
method to free the memory once the foreign object is no longer needed,
otherwise you'll be faced with memory leaks. This generic function is
called automatically by @cffi{} when passing objects to foreign
functions. Let's do that:
@lisp
;;; @lispcmt{Free strings allocated by translate-to-foreign.}
(defmethod free-translated-object (pointer (type my-string-type) param)
(declare (ignore param))
(foreign-string-free pointer))
@end lisp
@noindent
In this specific example, we don't need the @var{param} argument, so
we ignore it. See @ref{free-translated-object}, for an explanation of
its purpose and how you can use it.
A type translator does not necessarily need to convert the value. For
example, one could define a typedef for @code{:pointer} that ensures,
in the @code{translate-to-foreign} method, that the value is not a
null pointer, signalling an error if a null pointer is passed. This
would prevent some pointer errors when calling foreign functions that
cannot handle null pointers.
@strong{Please note:} these methods are meant as extensible hooks
only, and you should not call them directly. Use
@code{convert-to-foreign}, @code{convert-from-foreign} and
@code{free-converted-object} instead.
@xref{Tutorial-Types,, Defining new types}, for another example of
type translators.
@node Optimizing Type Translators, Foreign Structure Types, Foreign Type Translators, Foreign Types
@section Optimizing Type Translators
@cindex type translators, optimizing
@cindex compiler macros for type translation
@cindex defining type-translation compiler macros
Being based on generic functions, the type translation mechanism
described above can add a bit of overhead. This is usually not
significant, but we nevertheless provide a way of getting rid of the
overhead for the cases where it matters.
A good way to understand this issue is to look at the code generated
by @code{defcfun}. Consider the following example using the previously
defined @code{my-string} type:
@lisp
CFFI> (macroexpand-1 '(defcfun foo my-string (x my-string)))
;; @lispcmt{(simplified, downcased, etc...)}
(defun foo (x)
(multiple-value-bind (#:G2019 #:PARAM3149)
(translate-to-foreign x #<MY-STRING-TYPE @{11ED5A79@}>)
(unwind-protect
(translate-from-foreign
(foreign-funcall "foo" :pointer #:G2019 :pointer)
#<MY-STRING-TYPE @{11ED5659@}>)
(free-translated-object #:G2019 #<MY-STRING-TYPE @{11ED51A79@}>
#:PARAM3149))))
@end lisp
@noindent
In order to get rid of those generic function calls, @cffi{} has
another set of extensible generic functions that provide functionality
similar to @acronym{CL}'s compiler macros:
@code{expand-to-foreign-dyn}, @code{expand-to-foreign} and
@code{expand-from-foreign}. Here's how one could define a
@code{my-boolean} with them:
@lisp
(define-foreign-type my-boolean-type ()
()
(:actual-type :int)
(:simple-parser my-boolean))
(defmethod expand-to-foreign (value (type my-boolean-type))
`(if ,value 1 0))
(defmethod expand-from-foreign (value (type my-boolean-type))
`(not (zerop ,value)))
@end lisp
@noindent
And here's what the macroexpansion of a function using this type would
look like:
@lisp
CFFI> (macroexpand-1 '(defcfun bar my-boolean (x my-boolean)))
;; @lispcmt{(simplified, downcased, etc...)}
(defun bar (x)
(let ((#:g3182 (if x 1 0)))
(not (zerop (foreign-funcall "bar" :int #:g3182 :int)))))
@end lisp
@noindent
No generic function overhead.
Let's go back to our @code{my-string} type. The expansion interface
has no equivalent of @code{free-translated-object}; you must instead
define a method on @code{expand-to-foreign-dyn}, the third generic
function in this interface. This is especially useful when you can
allocate something much more efficiently if you know the object has
dynamic extent, as is the case with function calls that don't save the
relevant allocated arguments.
This exactly what we need for the @code{my-string} type:
@lisp
(defmethod expand-from-foreign (form (type my-string-type))
`(foreign-string-to-lisp ,form))
(defmethod expand-to-foreign-dyn (value var body (type my-string-type))
(let ((encoding (string-type-encoding type)))
`(with-foreign-string (,var ,value :encoding ',encoding)
,@@body)))
@end lisp
@noindent
So let's look at the macro expansion:
@lisp
CFFI> (macroexpand-1 '(defcfun foo my-string (x my-string)))
;; @lispcmt{(simplified, downcased, etc...)}
(defun foo (x)
(with-foreign-string (#:G2021 X :encoding ':utf-8)
(foreign-string-to-lisp
(foreign-funcall "foo" :pointer #:g2021 :pointer))))
@end lisp
@noindent
Again, no generic function overhead.
@subheading Other details
To short-circuit expansion and use the @code{translate-*} functions
instead, simply call the next method. Return its result in cases
where your method cannot generate an appropriate replacement for it.
This analogous to the @code{&whole form} mechanism compiler macros
provide.
The @code{expand-*} methods have precedence over their
@code{translate-*} counterparts and are guaranteed to be used in
@code{defcfun}, @code{foreign-funcall}, @code{defcvar} and
@code{defcallback}. If you define a method on each of the
@code{expand-*} generic functions, you are guaranteed to have full
control over the expressions generated for type translation in these
macros.
They may or may not be used in other @cffi{} operators that need to
translate between Lisp and C data; you may only assume that
@code{expand-*} methods will probably only be called during Lisp
compilation.
@code{expand-to-foreign-dyn} has precedence over
@code{expand-to-foreign} and is only used in @code{defcfun} and
@code{foreign-funcall}, only making sense in those contexts.
@strong{Important note:} this set of generic functions is called at
macroexpansion time. Methods are defined when loaded or evaluated,
not compiled. You are responsible for ensuring that your
@code{expand-*} methods are defined when the @code{foreign-funcall} or
other forms that use them are compiled. One way to do this is to put
the method definitions earlier in the file and inside an appropriate
@code{eval-when} form; another way is to always load a separate Lisp
or @acronym{FASL} file containing your @code{expand-*} definitions
before compiling files with forms that ought to use them. Otherwise,
they will not be found and the runtime translators will be used
instead.
@node Foreign Structure Types, Allocating Foreign Objects, Optimizing Type Translators, Foreign Types
@section Foreign Structure Types
For more involved C types than simple aliases to built-in types, such
as you can make with @code{defctype}, @cffi{} allows declaration of
structures and unions with @code{defcstruct} and @code{defcunion}.
For example, consider this fictional C structure declaration holding
some personal information:
@example
struct person @{
int number;
char* reason;
@};
@end example
@noindent
The equivalent @code{defcstruct} form follows:
@lisp
(defcstruct person
(number :int)
(reason :string))
@end lisp
@c LMH structure translation
By default, @ref{convert-from-foreign} (and also @ref{mem-ref}) will
make a plist with slot names as keys, and @ref{convert-to-foreign} will
translate such a plist to a foreign structure. A user wishing to define
other translations should use the @code{:class} argument to
@ref{defcstruct}, and then define methods for
@ref{translate-from-foreign} and
@ref{translate-into-foreign-memory} that specialize on this class,
possibly calling @code{call-next-method} to translate from and to the
plists rather than provide a direct interface to the foreign object.
The macro @code{translation-forms-for-class} will generate the forms
necessary to translate a Lisp class into a foreign structure and vice
versa.
@c Write separate function doc section for translation-forms-for-class?
@c Examples, perhaps taken from the tests?
Please note that this interface is only for those that must know about
the values contained in a relevant struct. If the library you are
interfacing returns an opaque pointer that needs only be passed to
other C library functions, by all means just use @code{:pointer} or a
type-safe definition munged together with @code{defctype} and type
translation. To pass or return a structure by value to a function, load
the cffi-libffi system and specify the structure as @code{(:struct
@var{structure-name})}. To pass or return the pointer, you can use
either @code{:pointer} or @code{(:pointer (:struct
@var{structure-name}))}.
@subheading Optimizing translate-into-foreign-memory
Just like how @ref{translate-from-foreign} had
@code{expand-from-foreign} to optimize away the generic function call
and @ref{translate-to-foreign} had the same in
@code{expand-to-foreign}, @ref{translate-into-foreign-memory} has
@code{expand-into-foreign-memory}.
Let's use our @code{person} struct in an example. However, we are
going to spice it up by using a lisp struct rather than a plist to
represent the person in lisp.
First we redefine @code{person} very slightly.
@lisp
(defcstruct (person :class c-person)
(number :int)
(reason :string))
@end lisp
By adding @code{:class} we can specialize the @code{translate-*}
methods on the type @code{c-person}.
Next we define a lisp struct to use instead of the plists.
@lisp
(defstruct lisp-person
(number 0 :type integer)
(reason "" :type string))
@end lisp
And now let's define the type translators we know already:
@lisp
(defmethod translate-from-foreign (ptr (type c-person))
(with-foreign-slots ((number reason) ptr (:struct person))
(make-lisp-person :number number :reason reason)))
(defmethod expand-from-foreign (ptr (type c-person))
`(with-foreign-slots ((number reason) ,ptr (:struct person))
(make-lisp-person :number number :reason reason)))
(defmethod translate-into-foreign-memory (value (type c-person) ptr)
(with-foreign-slots ((number reason) ptr (:struct person))
(setf number (lisp-person-number value)
reason (lisp-person-reason value))))
@end lisp
At this point everything works, we can convert to and from our
@code{lisp-person} and foreign @code{person}. If we macroexpand
@lisp
(setf (mem-aref ptr '(:struct person)) x)
@end lisp
we get something like:
@lisp
(let ((#:store879 x))
(translate-into-foreign-memory #:store879 #<c-person person>
(inc-pointer ptr 0))
#:store879)
@end lisp
Which is good, but now we can do better and get rid of that generic
function call to @code{translate-into-foreign-memory}.
@lisp
(defmethod expand-into-foreign-memory (value (type c-person) ptr)
`(with-foreign-slots ((number reason) ,ptr (:struct person))
(setf number (lisp-person-number ,value)
reason (lisp-person-reason ,value))))
@end lisp
Now we can expand again so see the changes:
@lisp
;; this:
(setf (mem-aref ptr '(:struct person)) x)
;; expands to this
;; (simplified, downcased, etc..)
(let ((#:store887 x))
(with-foreign-slots ((number reason) (inc-pointer ptr 0) (:struct person))
(setf number (lisp-person-number #:store887)
reason (lisp-person-reason #:store887))) #:store887)
@end lisp
And there we are, no generic function overhead.
@subheading Compatibility note
Previous versions of CFFI accepted the
``bare'' @var{structure-name} as a type specification, which was
interpreted as a pointer to the structure. This is deprecated and
produces a style warning. Using this deprecated form means that
@ref{mem-aref} retains its prior meaning and returns a pointer. Using
the @code{(:struct @var{structure-name})} form for the type,
@ref{mem-aref} provides a Lisp object translated from the
structure (by default a plist). Thus the semantics are consistent with all
types in returning the object as represented in Lisp, and not a pointer,
with the exception of the ``bare'' structure compatibility retained.
In order to obtain the pointer, you should use the function @ref{mem-aptr}.
See @ref{defcstruct} for more details.
@node Allocating Foreign Objects, convert-from-foreign, Foreign Structure Types, Foreign Types
@section Allocating Foreign Objects
@c I moved this because I moved with-foreign-object to the Pointers
@c chapter, where foreign-alloc is.
@xref{Allocating Foreign Memory}.
@c ===================================================================
@c CONVERT-FROM-FOREIGN
@page
@node convert-from-foreign, convert-to-foreign, Allocating Foreign Objects, Foreign Types
@heading convert-from-foreign
@subheading Syntax
@Function{convert-from-foreign foreign-value type @res{} value}
@subheading Arguments and Values
@table @var
@item foreign-value
The primitive C value as returned from a primitive foreign function or
from @code{convert-to-foreign}.
@item type
A @cffi{} type specifier.
@item value
The Lisp value translated from @var{foreign-value}.
@end table
@subheading Description
This is an external interface to the type translation facility. In
the implementation, all foreign functions are ultimately defined as
type translation wrappers around primitive foreign function
invocations.
This function is available mostly for inspection of the type
translation process, and possibly optimization of special cases of
your foreign function calls.
Its behavior is better described under @code{translate-from-foreign}'s
documentation.
@subheading Examples
@lisp
CFFI-USER> (convert-to-foreign "a boat" :string)
@result{} #<FOREIGN-ADDRESS #x097ACDC0>
@result{} T
CFFI-USER> (convert-from-foreign * :string)
@result{} "a boat"
@end lisp
@subheading See Also
@seealso{convert-to-foreign} @*
@seealso{free-converted-object} @*
@seealso{translate-from-foreign}
@c ===================================================================
@c CONVERT-TO-FOREIGN
@page
@node convert-to-foreign, defbitfield, convert-from-foreign, Foreign Types
@heading convert-to-foreign
@subheading Syntax
@Function{convert-to-foreign value type @res{} foreign-value, alloc-params}
@subheading Arguments and Values
@table @var
@item value
The Lisp object to be translated to a foreign object.
@item type
A @cffi{} type specifier.
@item foreign-value
The primitive C value, ready to be passed to a primitive foreign
function.
@item alloc-params
Something of a translation state; you must pass it to
@code{free-converted-object} along with the foreign value for that to
work.
@end table
@subheading Description
This is an external interface to the type translation facility. In
the implementation, all foreign functions are ultimately defined as
type translation wrappers around primitive foreign function
invocations.
This function is available mostly for inspection of the type
translation process, and possibly optimization of special cases of
your foreign function calls.
Its behavior is better described under @code{translate-to-foreign}'s
documentation.
@subheading Examples
@lisp
CFFI-USER> (convert-to-foreign t :boolean)
@result{} 1
@result{} NIL
CFFI-USER> (convert-to-foreign "hello, world" :string)
@result{} #<FOREIGN-ADDRESS #x097C5F80>
@result{} T
CFFI-USER> (code-char (mem-aref * :char 5))
@result{} #\,
@end lisp
@subheading See Also
@seealso{convert-from-foreign} @*
@seealso{free-converted-object} @*
@seealso{translate-to-foreign}
@c ===================================================================
@c DEFBITFIELD
@page
@node defbitfield, defcstruct, convert-to-foreign, Foreign Types
@heading defbitfield
@subheading Syntax
@Macro{defbitfield name-and-options &body masks}
masks ::= [docstring] @{ (symbol value) @}* @*
name-and-options ::= name | (name &optional (base-type :int))
@subheading Arguments and Values
@table @var
@item name
The name of the new bitfield type.
@item docstring
A documentation string, ignored.
@item base-type
A symbol denoting a foreign type.
@item symbol
A Lisp symbol.
@item value
An integer representing a bitmask.
@end table
@subheading Description
The @code{defbitfield} macro is used to define foreign types that map
lists of symbols to integer values.
If @var{value} is omitted, it will be computed as follows: find the
greatest @var{value} previously used, including those so computed,
with only a single 1-bit in its binary representation (that is, powers
of two), and left-shift it by one. This rule guarantees that a
computed @var{value} cannot clash with previous values, but may clash
with future explicitly specified values.
Symbol lists will be automatically converted to values and vice versa
when being passed as arguments to or returned from foreign functions,
respectively. The same applies to any other situations where an object
of a bitfield type is expected.
Types defined with @code{defbitfield} canonicalize to @var{base-type}
which is @code{:int} by default.
@subheading Examples
@lisp
(defbitfield open-flags
(:rdonly #x0000)
:wronly ;@lispcmt{#x0001}
:rdwr ;@lispcmt{@dots{}}
:nonblock
:append
(:creat #x0200))
;; @lispcmt{etc@dots{}}
CFFI> (foreign-bitfield-symbols 'open-flags #b1101)
@result{} (:WRONLY :NONBLOCK :APPEND)
CFFI> (foreign-bitfield-value 'open-flags '(:rdwr :creat))
@result{} 514 ; #x0202
(defcfun ("open" unix-open) :int
(path :string)
(flags open-flags)
(mode :uint16)) ; unportable
CFFI> (unix-open "/tmp/foo" '(:wronly :creat) #o644)
@result{} #<an fd>
;;; @lispcmt{Consider also the following lispier wrapper around open()}
(defun lispier-open (path mode &rest flags)
(unix-open path flags mode))
@end lisp
@subheading See Also
@seealso{foreign-bitfield-value} @*
@seealso{foreign-bitfield-symbols}
@c ===================================================================
@c DEFCSTRUCT
@page
@node defcstruct, defcunion, defbitfield, Foreign Types
@heading defcstruct
@subheading Syntax
@Macro{defcstruct name-and-options &body doc-and-slots @res{} name}
name-and-options ::= structure-name | (structure-name &key size)
doc-and-slots ::= [docstring] @{ (slot-name slot-type &key count offset) @}*
@subheading Arguments and Values
@table @var
@item structure-name
The name of new structure type.
@item docstring
A documentation string, ignored.
@item slot-name
A symbol naming the slot. It must be unique among slot names in this
structure.
@item size
Use this option to override the size (in bytes) of the struct.
@item slot-type
The type specifier for the slot.
@item count
Used to declare an array of size @var{count} inside the
structure. Defaults to @code{1} as such an array and a single element
are semantically equivalent.
@item offset
Overrides the slot's offset. The next slot's offset is calculated
based on this one.
@end table
@subheading Description
This defines a new @cffi{} aggregate type akin to C @code{struct}s.
In other words, it specifies that foreign objects of the type
@var{structure-name} are groups of different pieces of data, or
``slots'', of the @var{slot-type}s, distinguished from each other by
the @var{slot-name}s. Each structure is located in memory at a
position, and the slots are allocated sequentially beginning at that
point in memory (with some padding allowances as defined by the C
@acronym{ABI}, unless otherwise requested by specifying an
@var{offset} from the beginning of the structure (offset 0).
In other words, it is isomorphic to the C @code{struct}, giving
several extra features.
There are two kinds of slots, for the two kinds of @cffi{} types:
@table @dfn
@item Simple
Contain a single instance of a type that canonicalizes to a built-in
type, such as @code{:long} or @code{:pointer}. Used for simple
@cffi{} types.
@item Aggregate
Contain an embedded structure or union, or an array of objects. Used
for aggregate @cffi{} types.
@end table
The use of @acronym{CLOS} terminology for the structure-related
features is intentional; structure definitions are very much like
classes with (far) fewer features.
@subheading Examples
@lisp
(defcstruct point
"Point structure."
(x :int)
(y :int))
CFFI> (with-foreign-object (ptr 'point)
;; @lispcmt{Initialize the slots}
(setf (foreign-slot-value ptr 'point 'x) 42
(foreign-slot-value ptr 'point 'y) 42)
;; @lispcmt{Return a list with the coordinates}
(with-foreign-slots ((x y) ptr point)
(list x y)))
@result{} (42 42)
@end lisp
@lisp
;; @lispcmt{Using the :size and :offset options to define a partial structure.}
;; @lispcmt{(this is useful when you are interested in only a few slots}
;; @lispcmt{of a big foreign structure)}
(defcstruct (foo :size 32)
"Some struct with 32 bytes."
; @lispcmt{<16 bytes we don't care about>}
(x :int :offset 16) ; @lispcmt{an int at offset 16}
(y :int) ; @lispcmt{another int at offset 16+sizeof(int)}
; @lispcmt{<a couple more bytes we don't care about>}
(z :char :offset 24)) ; @lispcmt{a char at offset 24}
; @lispcmt{<7 more bytes ignored (since size is 32)>}
CFFI> (foreign-type-size 'foo)
@result{} 32
@end lisp
@lisp
;;; @lispcmt{Using :count to define arrays inside of a struct.}
(defcstruct video_tuner
(name :char :count 32))
@end lisp
@subheading See Also
@seealso{foreign-slot-pointer} @*
@seealso{foreign-slot-value} @*
@seealso{with-foreign-slots}
@c ===================================================================
@c DEFCUNION
@page
@node defcunion, defctype, defcstruct, Foreign Types
@heading defcunion
@subheading Syntax
@Macro{defcunion name &body doc-and-slots @res{} name}
doc-and-slots ::= [docstring] @{ (slot-name slot-type &key count) @}*
@subheading Arguments and Values
@table @var
@item name
The name of new union type.
@item docstring
A documentation string, ignored.
@item slot-name
A symbol naming the slot.
@item slot-type
The type specifier for the slot.
@item count
Used to declare an array of size @var{count} inside the
structure.
@end table
@subheading Description
A union is a structure in which all slots have an offset of zero. It
is isomorphic to the C @code{union}. Therefore, you should use the
usual foreign structure operations for accessing a union's slots.
@subheading Examples
@lisp
(defcunion uint32-bytes
(int-value :unsigned-int)
(bytes :unsigned-char :count 4))
@end lisp
@subheading See Also
@seealso{foreign-slot-pointer} @*
@seealso{foreign-slot-value}
@c ===================================================================
@c DEFCTYPE
@page
@node defctype, defcenum, defcunion, Foreign Types
@heading defctype
@subheading Syntax
@Macro{defctype name base-type &optional documentation}
@subheading Arguments and Values
@table @var
@item name
The name of the new foreign type.
@item base-type
A symbol or a list defining the new type.
@item documentation
A documentation string, currently ignored.
@end table
@subheading Description
The @code{defctype} macro provides a mechanism similar to C's
@code{typedef} to define new types. The new type inherits
@var{base-type}'s translators, if any. There is no way to define
translations for types defined with @code{defctype}. For that,
you should use @ref{define-foreign-type}.
@subheading Examples
@lisp
(defctype my-string :string
"My own string type.")
(defctype long-bools (:boolean :long)
"Booleans that map to C longs.")
@end lisp
@subheading See Also
@seealso{define-foreign-type}
@c ===================================================================
@c DEFCENUM
@page
@node defcenum, define-foreign-type, defctype, Foreign Types
@heading defcenum
@subheading Syntax
@Macro{defcenum name-and-options &body enum-list}
enum-list ::= [docstring] @{ keyword | (keyword value) @}*
name-and-options ::= name | (name &optional (base-type :int))
@subheading Arguments and Values
@table @var
@item name
The name of the new enum type.
@item docstring
A documentation string, ignored.
@item base-type
A symbol denoting a foreign type.
@item keyword
A keyword symbol.
@item value
An index value for a keyword.
@end table
@subheading Description
The @code{defcenum} macro is used to define foreign types that map
keyword symbols to integer values, similar to the C @code{enum} type.
If @var{value} is omitted its value will either be 0, if it's the
first entry, or it it will continue the progression from the last
specified value.
Keywords will be automatically converted to values and vice-versa when
being passed as arguments to or returned from foreign functions,
respectively. The same applies to any other situations where an object
of an @code{enum} type is expected.
Types defined with @code{defcenum} canonicalize to @var{base-type}
which is @code{:int} by default.
@subheading Examples
@lisp
(defcenum boolean
:no
:yes)
CFFI> (foreign-enum-value 'boolean :no)
@result{} 0
@end lisp
@lisp
(defcenum numbers
(:one 1)
:two
(:four 4))
CFFI> (foreign-enum-keyword 'numbers 2)
@result{} :TWO
@end lisp
@subheading See Also
@seealso{foreign-enum-value} @*
@seealso{foreign-enum-keyword}
@c ===================================================================
@c DEFINE-FOREIGN-TYPE
@page
@node define-foreign-type, define-parse-method, defcenum, Foreign Types
@heading define-foreign-type
@subheading Syntax
@Macro{define-foreign-type class-name supers slots &rest options @res{} class-name}
options ::= (@code{:actual-type} @var{type}) | @
(@code{:simple-parser} @var{symbol}) | @
@emph{regular defclass option}
@subheading Arguments and Values
@table @var
@item class-name
A symbol naming the new foreign type class.
@item supers
A list of symbols naming the super classes.
@item slots
A list of slot definitions, passed to @code{defclass}.
@end table
@subheading Description
@c TODO rewrite
The macro @code{define-foreign-type} defines a new class
@var{class-name}. It is a thin wrapper around @code{defclass}. Among
other things, it ensures that @var{class-name} becomes a subclass of
@var{foreign-type}, what you need to know about that is that there's
an initarg @code{:actual-type} which serves the same purpose as
@code{defctype}'s @var{base-type} argument.
@c TODO mention the type translators here
@c FIX FIX
@subheading Examples
Taken from @cffi{}'s @code{:boolean} type definition:
@lisp
(define-foreign-type :boolean (&optional (base-type :int))
"Boolean type. Maps to an :int by default. Only accepts integer types."
(ecase base-type
((:char
:unsigned-char
:int
:unsigned-int
:long
:unsigned-long) base-type)))
CFFI> (canonicalize-foreign-type :boolean)
@result{} :INT
CFFI> (canonicalize-foreign-type '(:boolean :long))
@result{} :LONG
CFFI> (canonicalize-foreign-type '(:boolean :float))
;; @lispcmt{@error{} signalled by ECASE.}
@end lisp
@subheading See Also
@seealso{defctype} @*
@seealso{define-parse-method}
@c ===================================================================
@c DEFINE-PARSE-METHOD
@page
@node define-parse-method, foreign-bitfield-symbols, define-foreign-type, Foreign Types
@heading define-parse-method
@subheading Syntax
@Macro{define-parse-method name lambda-list &body body @res{} name}
@subheading Arguments and Values
@table @var
@item type-name
A symbol naming the new foreign type.
@item lambda-list
A lambda list which is the argument list of the new foreign type.
@item body
One or more forms that provide a definition of the new foreign type.
@end table
@subheading Description
@c TODO: update example. The boolean type is probably a good choice.
@subheading Examples
Taken from @cffi{}'s @code{:boolean} type definition:
@lisp
(define-foreign-type :boolean (&optional (base-type :int))
"Boolean type. Maps to an :int by default. Only accepts integer types."
(ecase base-type
((:char
:unsigned-char
:int
:unsigned-int
:long
:unsigned-long) base-type)))
CFFI> (canonicalize-foreign-type :boolean)
@result{} :INT
CFFI> (canonicalize-foreign-type '(:boolean :long))
@result{} :LONG
CFFI> (canonicalize-foreign-type '(:boolean :float))
;; @lispcmt{@error{} signalled by ECASE.}
@end lisp
@subheading See Also
@seealso{define-foreign-type}
@c ===================================================================
@c EXPLAIN-FOREIGN-SLOT-VALUE
@c @node explain-foreign-slot-value
@c @heading explain-foreign-slot-value
@c @subheading Syntax
@c @Macro{explain-foreign-slot-value ptr type &rest slot-names}
@c @subheading Arguments and Values
@c @table @var
@c @item ptr
@c ...
@c @item type
@c ...
@c @item slot-names
@c ...
@c @end table
@c @subheading Description
@c This macro translates the slot access that would occur by calling
@c @code{foreign-slot-value} with the same arguments into an equivalent
@c expression in C and prints it to @code{*standard-output*}.
@c @emph{Note: this is not implemented yet.}
@c @subheading Examples
@c @lisp
@c CFFI> (explain-foreign-slot-value ptr 'timeval 'tv-secs)
@c @result{} ptr->tv_secs
@c CFFI> (explain-foreign-slot-value emp 'employee 'hire-date 'tv-usecs)
@c @result{} emp->hire_date.tv_usecs
@c @end lisp
@c @subheading See Also
@c ===================================================================
@c FOREIGN-BITFIELD-SYMBOLS
@page
@node foreign-bitfield-symbols, foreign-bitfield-value, define-parse-method, Foreign Types
@heading foreign-bitfield-symbols
@subheading Syntax
@Function{foreign-bitfield-symbols type value @res{} symbols}
@subheading Arguments and Values
@table @var
@item type
A bitfield type.
@item value
An integer.
@item symbols
A potentially shared list of symbols.
@code{nil}.
@end table
@subheading Description
The function @code{foreign-bitfield-symbols} returns a possibly shared
list of symbols that correspond to @var{value} in @var{type}.
@subheading Examples
@lisp
(defbitfield flags
(flag-a 1)
(flag-b 2)
(flag-c 4))
CFFI> (foreign-bitfield-symbols 'flags #b101)
@result{} (FLAG-A FLAG-C)
@end lisp
@subheading See Also
@seealso{defbitfield} @*
@seealso{foreign-bitfield-value}
@c ===================================================================
@c FOREIGN-BITFIELD-VALUE
@page
@node foreign-bitfield-value, foreign-enum-keyword, foreign-bitfield-symbols, Foreign Types
@heading foreign-bitfield-value
@subheading Syntax
@Function{foreign-bitfield-value type symbols @res{} value}
@subheading Arguments and Values
@table @var
@item type
A @code{bitfield} type.
@item symbol
A Lisp symbol.
@item value
An integer.
@end table
@subheading Description
The function @code{foreign-bitfield-value} returns the @var{value} that
corresponds to the symbols in the @var{symbols} list.
@subheading Examples
@lisp
(defbitfield flags
(flag-a 1)
(flag-b 2)
(flag-c 4))
CFFI> (foreign-bitfield-value 'flags '(flag-a flag-c))
@result{} 5 ; #b101
@end lisp
@subheading See Also
@seealso{defbitfield} @*
@seealso{foreign-bitfield-symbols}
@c ===================================================================
@c FOREIGN-ENUM-KEYWORD
@page
@node foreign-enum-keyword, foreign-enum-value, foreign-bitfield-value, Foreign Types
@heading foreign-enum-keyword
@subheading Syntax
@Function{foreign-enum-keyword type value &key errorp @res{} keyword}
@subheading Arguments and Values
@table @var
@item type
An @code{enum} type.
@item value
An integer.
@item errorp
If true (the default), signal an error if @var{value} is not defined
in @var{type}. If false, @code{foreign-enum-keyword} returns
@code{nil}.
@item keyword
A keyword symbol.
@end table
@subheading Description
The function @code{foreign-enum-keyword} returns the keyword symbol
that corresponds to @var{value} in @var{type}.
An error is signaled if @var{type} doesn't contain such @var{value}
and @var{errorp} is true.
@subheading Examples
@lisp
(defcenum boolean
:no
:yes)
CFFI> (foreign-enum-keyword 'boolean 1)
@result{} :YES
@end lisp
@subheading See Also
@seealso{defcenum} @*
@seealso{foreign-enum-value}
@c ===================================================================
@c FOREIGN-ENUM-VALUE
@page
@node foreign-enum-value, foreign-slot-names, foreign-enum-keyword, Foreign Types
@heading foreign-enum-value
@subheading Syntax
@Function{foreign-enum-value type keyword &key errorp @res{} value}
@subheading Arguments and Values
@table @var
@item type
An @code{enum} type.
@item keyword
A keyword symbol.
@item errorp
If true (the default), signal an error if @var{keyword} is not
defined in @var{type}. If false, @code{foreign-enum-value} returns
@code{nil}.
@item value
An integer.
@end table
@subheading Description
The function @code{foreign-enum-value} returns the @var{value} that
corresponds to @var{keyword} in @var{type}.
An error is signaled if @var{type} doesn't contain such
@var{keyword}, and @var{errorp} is true.
@subheading Examples
@lisp
(defcenum boolean
:no
:yes)
CFFI> (foreign-enum-value 'boolean :yes)
@result{} 1
@end lisp
@subheading See Also
@seealso{defcenum} @*
@seealso{foreign-enum-keyword}
@c ===================================================================
@c FOREIGN-SLOT-NAMES
@page
@node foreign-slot-names, foreign-slot-offset, foreign-enum-value, Foreign Types
@heading foreign-slot-names
@subheading Syntax
@Function{foreign-slot-names type @res{} names}
@subheading Arguments and Values
@table @var
@item type
A foreign struct type.
@item names
A list.
@end table
@subheading Description
The function @code{foreign-slot-names} returns a potentially shared
list of slot @var{names} for the given structure @var{type}. This list
has no particular order.
@subheading Examples
@lisp
(defcstruct timeval
(tv-secs :long)
(tv-usecs :long))
CFFI> (foreign-slot-names '(:struct timeval))
@result{} (TV-SECS TV-USECS)
@end lisp
@subheading See Also
@seealso{defcstruct} @*
@seealso{foreign-slot-offset} @*
@seealso{foreign-slot-value} @*
@seealso{foreign-slot-pointer}
@c ===================================================================
@c FOREIGN-SLOT-OFFSET
@page
@node foreign-slot-offset, foreign-slot-pointer, foreign-slot-names, Foreign Types
@heading foreign-slot-offset
@subheading Syntax
@Function{foreign-slot-offset type slot-name @res{} offset}
@subheading Arguments and Values
@table @var
@item type
A foreign struct type.
@item slot-name
A symbol.
@item offset
An integer.
@end table
@subheading Description
The function @code{foreign-slot-offset} returns the @var{offset} in
bytes of a slot in a foreign struct type.
@subheading Examples
@lisp
(defcstruct timeval
(tv-secs :long)
(tv-usecs :long))
CFFI> (foreign-slot-offset '(:struct timeval) 'tv-secs)
@result{} 0
CFFI> (foreign-slot-offset '(:struct timeval) 'tv-usecs)
@result{} 4
@end lisp
@subheading See Also
@seealso{defcstruct} @*
@seealso{foreign-slot-names} @*
@seealso{foreign-slot-pointer} @*
@seealso{foreign-slot-value}
@c ===================================================================
@c FOREIGN-SLOT-POINTER
@page
@node foreign-slot-pointer, foreign-slot-value, foreign-slot-offset, Foreign Types
@heading foreign-slot-pointer
@subheading Syntax
@Function{foreign-slot-pointer ptr type slot-name @res{} pointer}
@subheading Arguments and Values
@table @var
@item ptr
A pointer to a structure.
@item type
A foreign structure type.
@item slot-names
A slot name in the @var{type}.
@item pointer
A pointer to the slot @var{slot-name}.
@end table
@subheading Description
Returns a pointer to the location of the slot @var{slot-name} in a
foreign object of type @var{type} at @var{ptr}. The returned pointer
points inside the structure. Both the pointer and the memory it points
to have the same extent as @var{ptr}.
For aggregate slots, this is the same value returned by
@code{foreign-slot-value}.
@subheading Examples
@lisp
(defcstruct point
"Pointer structure."
(x :int)
(y :int))
CFFI> (with-foreign-object (ptr '(:struct point))
(foreign-slot-pointer ptr '(:struct point) 'x))
@result{} #<FOREIGN-ADDRESS #xBFFF6E60>
;; @lispcmt{Note: the exact pointer representation varies from lisp to lisp.}
@end lisp
@subheading See Also
@seealso{defcstruct} @*
@seealso{foreign-slot-value} @*
@seealso{foreign-slot-names} @*
@seealso{foreign-slot-offset}
@c ===================================================================
@c FOREIGN-SLOT-VALUE
@page
@node foreign-slot-value, foreign-type-alignment, foreign-slot-pointer, Foreign Types
@heading foreign-slot-value
@subheading Syntax
@Accessor{foreign-slot-value ptr type slot-name @res{} object}
@subheading Arguments and Values
@table @var
@item ptr
A pointer to a structure.
@item type
A foreign structure type.
@item slot-name
A symbol naming a slot in the structure type.
@item object
The object contained in the slot specified by @var{slot-name}.
@end table
@subheading Description
For simple slots, @code{foreign-slot-value} returns the value of the
object, such as a Lisp integer or pointer. In C, this would be
expressed as @code{ptr->slot}.
For aggregate slots, a pointer inside the structure to the beginning
of the slot's data is returned. In C, this would be expressed as
@code{&ptr->slot}. This pointer and the memory it points to have the
same extent as @var{ptr}.
There are compiler macros for @code{foreign-slot-value} and its
@code{setf} expansion that open code the memory access when
@var{type} and @var{slot-names} are constant at compile-time.
@subheading Examples
@lisp
(defcstruct point
"Pointer structure."
(x :int)
(y :int))
CFFI> (with-foreign-object (ptr '(:struct point))
;; @lispcmt{Initialize the slots}
(setf (foreign-slot-value ptr '(:struct point) 'x) 42
(foreign-slot-value ptr '(:struct point) 'y) 42)
;; @lispcmt{Return a list with the coordinates}
(with-foreign-slots ((x y) ptr (:struct point))
(list x y)))
@result{} (42 42)
@end lisp
@subheading See Also
@seealso{defcstruct} @*
@seealso{foreign-slot-names} @*
@seealso{foreign-slot-offset} @*
@seealso{foreign-slot-pointer} @*
@seealso{with-foreign-slots}
@c ===================================================================
@c FOREIGN-TYPE-ALIGNMENT
@page
@node foreign-type-alignment, foreign-type-size, foreign-slot-value, Foreign Types
@heading foreign-type-alignment
@subheading Syntax
@c XXX: This is actually a generic function.
@Function{foreign-type-alignment type @res{} alignment}
@subheading Arguments and Values
@table @var
@item type
A foreign type.
@item alignment
An integer.
@end table
@subheading Description
The function @code{foreign-type-alignment} returns the
@var{alignment} of @var{type} in bytes.
@subheading Examples
@lisp
CFFI> (foreign-type-alignment :char)
@result{} 1
CFFI> (foreign-type-alignment :short)
@result{} 2
CFFI> (foreign-type-alignment :int)
@result{} 4
@end lisp
@lisp
(defcstruct foo
(a :char))
CFFI> (foreign-type-alignment '(:struct foo))
@result{} 1
@end lisp
@subheading See Also
@seealso{foreign-type-size}
@c ===================================================================
@c FOREIGN-TYPE-SIZE
@page
@node foreign-type-size, free-converted-object, foreign-type-alignment, Foreign Types
@heading foreign-type-size
@subheading Syntax
@c XXX: this is actually a generic function.
@Function{foreign-type-size type @res{} size}
@subheading Arguments and Values
@table @var
@item type
A foreign type.
@item size
An integer.
@end table
@subheading Description
The function @code{foreign-type-size} return the @var{size} of
@var{type} in bytes. This includes any padding within and following
the in-memory representation as needed to create an array of
@var{type} objects.
@subheading Examples
@lisp
(defcstruct foo
(a :double)
(c :char))
CFFI> (foreign-type-size :double)
@result{} 8
CFFI> (foreign-type-size :char)
@result{} 1
CFFI> (foreign-type-size '(:struct foo))
@result{} 16
@end lisp
@subheading See Also
@seealso{foreign-type-alignment}
@c ===================================================================
@c FREE-CONVERTED-OBJECT
@page
@node free-converted-object, free-translated-object, foreign-type-size, Foreign Types
@heading free-converted-object
@subheading Syntax
@Function{free-converted-object foreign-value type params}
@subheading Arguments and Values
@table @var
@item foreign-value
The C object to be freed.
@item type
A @cffi{} type specifier.
@item params
The state returned as the second value from @code{convert-to-foreign};
used to implement the third argument to @code{free-translated-object}.
@end table
@subheading Description
The return value is unspecified.
This is an external interface to the type translation facility. In
the implementation, all foreign functions are ultimately defined as
type translation wrappers around primitive foreign function
invocations.
This function is available mostly for inspection of the type
translation process, and possibly optimization of special cases of
your foreign function calls.
Its behavior is better described under @code{free-translated-object}'s
documentation.
@subheading Examples
@lisp
CFFI-USER> (convert-to-foreign "a boat" :string)
@result{} #<FOREIGN-ADDRESS #x097ACDC0>
@result{} T
CFFI-USER> (free-converted-object * :string t)
@result{} NIL
@end lisp
@subheading See Also
@seealso{convert-from-foreign} @*
@seealso{convert-to-foreign} @*
@seealso{free-translated-object}
@c ===================================================================
@c FREE-TRANSLATED-OBJECT
@c TODO: update
@page
@node free-translated-object, translate-from-foreign, free-converted-object, Foreign Types
@heading free-translated-object
@subheading Syntax
@GenericFunction{free-translated-object value type-name param}
@subheading Arguments and Values
@table @var
@item pointer
The foreign value returned by @code{translate-to-foreign}.
@item type-name
A symbol naming a foreign type defined by @code{defctype}.
@item param
The second value, if any, returned by @code{translate-to-foreign}.
@end table
@subheading Description
This generic function may be specialized by user code to perform
automatic deallocation of foreign objects as they are passed to C
functions.
Any methods defined on this generic function must EQL-specialize the
@var{type-name} parameter on a symbol defined as a foreign type by
the @code{defctype} macro.
@subheading See Also
@seealso{Foreign Type Translators} @*
@seealso{translate-to-foreign}
@c ===================================================================
@c TRANSLATE-FROM-FOREIGN
@c TODO: update
@page
@node translate-from-foreign, translate-to-foreign, free-translated-object, Foreign Types
@heading translate-from-foreign
@subheading Syntax
@GenericFunction{translate-from-foreign foreign-value type-name @
@res{} lisp-value}
@subheading Arguments and Values
@table @var
@item foreign-value
The foreign value to convert to a Lisp object.
@item type-name
A symbol naming a foreign type defined by @code{defctype}.
@item lisp-value
The lisp value to pass in place of @code{foreign-value} to Lisp code.
@end table
@subheading Description
This generic function is invoked by @cffi{} to convert a foreign value to
a Lisp value, such as when returning from a foreign function, passing
arguments to a callback function, or accessing a foreign variable.
To extend the @cffi{} type system by performing custom translations, this
method may be specialized by @sc{eql}-specializing @code{type-name} on a
symbol naming a foreign type defined with @code{defctype}. This
method should return the appropriate Lisp value to use in place of the
foreign value.
The results are undefined if the @code{type-name} parameter is
specialized in any way except an @sc{eql} specializer on a foreign type
defined with @code{defctype}. Specifically, translations may not be
defined for built-in types.
@subheading See Also
@seealso{Foreign Type Translators} @*
@seealso{translate-to-foreign} @*
@seealso{free-translated-object}
@c ===================================================================
@c TRANSLATE-TO-FOREIGN
@c TODO: update
@page
@node translate-to-foreign, translate-into-foreign-memory, translate-from-foreign, Foreign Types
@heading translate-to-foreign
@subheading Syntax
@GenericFunction{translate-to-foreign lisp-value type-name @
@res{} foreign-value, alloc-param}
@subheading Arguments and Values
@table @var
@item lisp-value
The Lisp value to convert to foreign representation.
@item type-name
A symbol naming a foreign type defined by @code{defctype}.
@item foreign-value
The foreign value to pass in place of @code{lisp-value} to foreign code.
@item alloc-param
If present, this value will be passed to
@code{free-translated-object}.
@end table
@subheading Description
This generic function is invoked by @cffi{} to convert a Lisp value to a
foreign value, such as when passing arguments to a foreign function,
returning a value from a callback, or setting a foreign variable. A
``foreign value'' is one appropriate for passing to the next-lowest
translator, including the low-level translators that are ultimately
invoked invisibly with @cffi{}.
To extend the @cffi{} type system by performing custom translations, this
method may be specialized by @sc{eql}-specializing @code{type-name} on a
symbol naming a foreign type defined with @code{defctype}. This
method should return the appropriate foreign value to use in place of
the Lisp value.
In cases where @cffi{} can determine the lifetime of the foreign object
returned by this method, it will invoke @code{free-translated-object}
on the foreign object at the appropriate time. If
@code{translate-to-foreign} returns a second value, it will be passed
as the @code{param} argument to @code{free-translated-object}. This
can be used to establish communication between the allocation and
deallocation methods.
The results are undefined if the @code{type-name} parameter is
specialized in any way except an @sc{eql} specializer on a foreign type
defined with @code{defctype}. Specifically, translations may not be
defined for built-in types.
@subheading See Also
@seealso{Foreign Type Translators} @*
@seealso{translate-from-foreign} @*
@seealso{free-translated-object}
@c ===================================================================
@c TRANSLATE-INTO-FOREIGN-MEMORY
@page
@node translate-into-foreign-memory, with-foreign-slots, translate-to-foreign, Foreign Types
@heading translate-into-foreign-memory
@subheading Syntax
@GenericFunction{translate-into-foreign-memory lisp-value type-name pointer}
@subheading Arguments and Values
@table @var
@item lisp-value
The Lisp value to convert to foreign representation.
@item type-name
A symbol or list @code{(:struct @var{structure-name})} naming a foreign type defined by @code{defctype}.
@item pointer
The foreign pointer where the translated object should be stored.
@end table
@subheading Description
Translate the Lisp value into the foreign memory location given by
pointer. The return value is not used.
@c ===================================================================
@c WITH-FOREIGN-SLOTS
@page
@node with-foreign-slots, , translate-into-foreign-memory, Foreign Types
@heading with-foreign-slots
@subheading Syntax
@Macro{with-foreign-slots (vars ptr type) &body body}
@subheading Arguments and Values
@table @var
@item vars
A list with each element a symbol, or list of length two with the
first element @code{:pointer} and the second a symbol.
@item ptr
A foreign pointer to a structure.
@item type
A structure type.
@item body
A list of forms to be executed.
@end table
@subheading Description
The @code{with-foreign-slots} macro creates local symbol macros for each
var in @var{vars} to reference foreign slots in @var{ptr} of @var{type}.
If the var is a list starting with @code{:pointer}, it will bind the
pointer to the slot (rather than the value). It is similar to Common
Lisp's @code{with-slots} macro.
@subheading Examples
@lisp
(defcstruct tm
(sec :int)
(min :int)
(hour :int)
(mday :int)
(mon :int)
(year :int)
(wday :int)
(yday :int)
(isdst :boolean)
(zone :string)
(gmtoff :long))
CFFI> (with-foreign-object (time :int)
(setf (mem-ref time :int)
(foreign-funcall "time" :pointer (null-pointer) :int))
(foreign-funcall "gmtime" :pointer time (:pointer (:struct tm))))
@result{} #<A Mac Pointer #x102A30>
CFFI> (with-foreign-slots ((sec min hour mday mon year) * (:struct tm))
(format nil "~A:~A:~A, ~A/~A/~A"
hour min sec (+ 1900 year) mon mday))
@result{} "7:22:47, 2005/8/2"
@end lisp
@subheading See Also
@seealso{defcstruct} @*
@seealso{defcunion} @*
@seealso{foreign-slot-value}
@c ===================================================================
@c CHAPTER: Pointers
@node Pointers, Strings, Foreign Types, Top
@chapter Pointers
All C data in @cffi{} is referenced through pointers. This includes
defined C variables that hold immediate values, and integers.
To see why this is, consider the case of the C integer. It is not
only an arbitrary representation for an integer, congruent to Lisp's
fixnums; the C integer has a specific bit pattern in memory defined by
the C @acronym{ABI}. Lisp has no such constraint on its fixnums;
therefore, it only makes sense to think of fixnums as C integers if
you assume that @cffi{} converts them when necessary, such as when
storing one for use in a C function call, or as the value of a C
variable. This requires defining an area of memory@footnote{The
definition of @dfn{memory} includes the @acronym{CPU} registers.},
represented through an effective address, and storing it there.
Due to this compartmentalization, it only makes sense to manipulate
raw C data in Lisp through pointers to it. For example, while there
may be a Lisp representation of a @code{struct} that is converted to C
at store time, you may only manipulate its raw data through a pointer.
The C compiler does this also, albeit informally.
@menu
* Basic Pointer Operations::
* Allocating Foreign Memory::
* Accessing Foreign Memory::
Dictionary
* foreign-free::
* foreign-alloc::
* foreign-symbol-pointer::
* inc-pointer::
* incf-pointer::
* make-pointer::
* mem-aptr::
* mem-aref::
* mem-ref::
* null-pointer::
* null-pointer-p::
* pointerp::
* pointer-address::
* pointer-eq::
* with-foreign-object::
* with-foreign-objects::
* with-foreign-pointer::
@end menu
@node Basic Pointer Operations, Allocating Foreign Memory, Pointers, Pointers
@section Basic Pointer Operations
Manipulating pointers proper can be accomplished through most of the
other operations defined in the Pointers dictionary, such as
@code{make-pointer}, @code{pointer-address}, and @code{pointer-eq}.
When using them, keep in mind that they merely manipulate the Lisp
representation of pointers, not the values they point to.
@deftp {Lisp Type} foreign-pointer
The pointers' representations differ from implementation to
implementation and have different types. @code{foreign-pointer}
provides a portable type alias to each of these types.
@end deftp
@node Allocating Foreign Memory, Accessing Foreign Memory, Basic Pointer Operations, Pointers
@section Allocating Foreign Memory
@cffi{} provides support for stack and heap C memory allocation.
Stack allocation, done with @code{with-foreign-object}, is sometimes
called ``dynamic'' allocation in Lisp, because memory allocated as
such has dynamic extent, much as with @code{let} bindings of special
variables.
This should not be confused with what C calls ``dynamic'' allocation,
or that done with @code{malloc} and friends. This sort of heap
allocation is done with @code{foreign-alloc}, creating objects that
exist until freed with @code{foreign-free}.
@node Accessing Foreign Memory, foreign-free, Allocating Foreign Memory, Pointers
@section Accessing Foreign Memory
When manipulating raw C data, consider that all pointers are pointing
to an array. When you only want one C value, such as a single
@code{struct}, this array only has one such value. It is worthwhile
to remember that everything is an array, though, because this is also
the semantic that C imposes natively.
C values are accessed as the @code{setf}-able places defined by
@code{mem-aref} and @code{mem-ref}. Given a pointer and a @cffi{}
type (@pxref{Foreign Types}), either of these will dereference the
pointer, translate the C data there back to Lisp, and return the
result of said translation, performing the reverse operation when
@code{setf}-ing. To decide which one to use, consider whether you
would use the array index operator @code{[@var{n}]} or the pointer
dereference @code{*} in C; use @code{mem-aref} for array indexing and
@code{mem-ref} for pointer dereferencing.
@c ===================================================================
@c FOREIGN-FREE
@page
@node foreign-free, foreign-alloc, Accessing Foreign Memory, Pointers
@heading foreign-free
@subheading Syntax
@Function{foreign-free ptr @res{} undefined}
@subheading Arguments and Values
@table @var
@item ptr
A foreign pointer.
@end table
@subheading Description
The @code{foreign-free} function frees a @code{ptr} previously
allocated by @code{foreign-alloc}. The consequences of freeing a given
pointer twice are undefined.
@subheading Examples
@lisp
CFFI> (foreign-alloc :int)
@result{} #<A Mac Pointer #x1022E0>
CFFI> (foreign-free *)
@result{} NIL
@end lisp
@subheading See Also
@seealso{foreign-alloc} @*
@seealso{with-foreign-pointer}
@c ===================================================================
@c FOREIGN-ALLOC
@page
@node foreign-alloc, foreign-symbol-pointer, foreign-free, Pointers
@heading foreign-alloc
@subheading Syntax
@Function{foreign-alloc type &key initial-element initial-contents (count 1) @
null-terminated-p @res{} pointer}
@subheading Arguments and Values
@table @var
@item type
A foreign type.
@item initial-element
A Lisp object.
@item initial-contents
A sequence.
@item count
An integer. Defaults to 1 or the length of @var{initial-contents} if
supplied.
@item null-terminated-p
A boolean, false by default.
@item pointer
A foreign pointer to the newly allocated memory.
@end table
@subheading Description
The @code{foreign-alloc} function allocates enough memory to hold
@var{count} objects of type @var{type} and returns a
@var{pointer}. This memory must be explicitly freed using
@code{foreign-free} once it is no longer needed.
If @var{initial-element} is supplied, it is used to initialize the
@var{count} objects the newly allocated memory holds.
If an @var{initial-contents} sequence is supplied, it must have a
length less than or equal to @var{count} and each of its elements
will be used to initialize the contents of the newly allocated
memory.
If @var{count} is omitted and @var{initial-contents} is specified, it
will default to @code{(length @var{initial-contents})}.
@var{initial-element} and @var{initial-contents} are mutually
exclusive.
When @var{null-terminated-p} is true,
@code{(1+ (max @var{count} (length @var{initial-contents})))} elements
are allocated and the last one is set to @code{NULL}. Note that in
this case @var{type} must be a pointer type (ie. a type that
canonicalizes to @code{:pointer}), otherwise an error is signaled.
@subheading Examples
@lisp
CFFI> (foreign-alloc :char)
@result{} #<A Mac Pointer #x102D80> ; @lispcmt{A pointer to 1 byte of memory.}
CFFI> (foreign-alloc :char :count 20)
@result{} #<A Mac Pointer #x1024A0> ; @lispcmt{A pointer to 20 bytes of memory.}
CFFI> (foreign-alloc :int :initial-element 12)
@result{} #<A Mac Pointer #x1028B0>
CFFI> (mem-ref * :int)
@result{} 12
CFFI> (foreign-alloc :int :initial-contents '(1 2 3))
@result{} #<A Mac Pointer #x102950>
CFFI> (loop for i from 0 below 3
collect (mem-aref * :int i))
@result{} (1 2 3)
CFFI> (foreign-alloc :int :initial-contents #(1 2 3))
@result{} #<A Mac Pointer #x102960>
CFFI> (loop for i from 0 below 3
collect (mem-aref * :int i))
@result{} (1 2 3)
;;; @lispcmt{Allocate a char** pointer that points to newly allocated memory}
;;; @lispcmt{by the :string type translator for the string "foo".}
CFFI> (foreign-alloc :string :initial-element "foo")
@result{} #<A Mac Pointer #x102C40>
@end lisp
@lisp
;;; @lispcmt{Allocate a null-terminated array of strings.}
;;; @lispcmt{(Note: FOREIGN-STRING-TO-LISP returns NIL when passed a null pointer)}
CFFI> (foreign-alloc :string
:initial-contents '("foo" "bar" "baz")
:null-terminated-p t)
@result{} #<A Mac Pointer #x102D20>
CFFI> (loop for i from 0 below 4
collect (mem-aref * :string i))
@result{} ("foo" "bar" "baz" NIL)
CFFI> (progn
(dotimes (i 3)
(foreign-free (mem-aref ** :pointer i)))
(foreign-free **))
@result{} nil
@end lisp
@subheading See Also
@seealso{foreign-free} @*
@seealso{with-foreign-object} @*
@seealso{with-foreign-pointer}
@c ===================================================================
@c FOREIGN-SYMBOL-POINTER
@page
@node foreign-symbol-pointer, inc-pointer, foreign-alloc, Pointers
@heading foreign-symbol-pointer
@subheading Syntax
@Function{foreign-symbol-pointer foreign-name &key library @res{} pointer}
@subheading Arguments and Values
@table @var
@item foreign-name
A string.
@item pointer
A foreign pointer, or @code{nil}.
@item library
A Lisp symbol or an instance of @code{foreign-library}.
@end table
@subheading Description
The function @code{foreign-symbol-pointer} will return a foreign
pointer corresponding to the foreign symbol denoted by the string
@var{foreign-name}. If a foreign symbol named @var{foreign-name}
doesn't exist, @code{nil} is returned.
ABI name manglings will be performed on @var{foreign-name} by
@code{foreign-symbol-pointer} if necessary. (eg: adding a leading
underscore on darwin/ppc)
@var{library} should name a foreign library as defined by
@code{define-foreign-library}, @code{:default} (which is the default)
or an instance of @code{foreign-library} as returned by
@code{load-foreign-library}.
@strong{Important note:} do not keep these pointers across saved Lisp
cores as the foreign-library may move across sessions.
@subheading Examples
@lisp
CFFI> (foreign-symbol-pointer "errno")
@result{} #<A Mac Pointer #xA0008130>
CFFI> (foreign-symbol-pointer "strerror")
@result{} #<A Mac Pointer #x9002D0F8>
CFFI> (foreign-funcall-pointer * () :int (mem-ref ** :int) :string)
@result{} "No such file or directory"
CFFI> (foreign-symbol-pointer "inexistent symbol")
@result{} NIL
@end lisp
@subheading See Also
@seealso{defcvar}
@c ===================================================================
@c INC-POINTER
@page
@node inc-pointer, incf-pointer, foreign-symbol-pointer, Pointers
@heading inc-pointer
@subheading Syntax
@Function{inc-pointer pointer offset @res{} new-pointer}
@subheading Arguments and Values
@table @var
@item pointer
@itemx new-pointer
A foreign pointer.
@item offset
An integer.
@end table
@subheading Description
The function @code{inc-pointer} will return a @var{new-pointer} pointing
@var{offset} bytes past @var{pointer}.
@subheading Examples
@lisp
CFFI> (foreign-string-alloc "Common Lisp")
@result{} #<A Mac Pointer #x102EA0>
CFFI> (inc-pointer * 7)
@result{} #<A Mac Pointer #x102EA7>
CFFI> (foreign-string-to-lisp *)
@result{} "Lisp"
@end lisp
@subheading See Also
@seealso{incf-pointer} @*
@seealso{make-pointer} @*
@seealso{pointerp} @*
@seealso{null-pointer} @*
@seealso{null-pointer-p}
@c ===================================================================
@c INCF-POINTER
@page
@node incf-pointer, make-pointer, inc-pointer, Pointers
@heading incf-pointer
@subheading Syntax
@Macro{incf-pointer place &optional (offset 1) @res{} new-pointer}
@subheading Arguments and Values
@table @var
@item place
A @code{setf} place.
@item new-pointer
A foreign pointer.
@item offset
An integer.
@end table
@subheading Description
The @code{incf-pointer} macro takes the foreign pointer from
@var{place} and creates a @var{new-pointer} incremented by
@var{offset} bytes and which is stored in @var{place}.
@subheading Examples
@lisp
CFFI> (defparameter *two-words* (foreign-string-alloc "Common Lisp"))
@result{} *TWO-WORDS*
CFFI> (defparameter *one-word* *two-words*)
@result{} *ONE-WORD*
CFFI> (incf-pointer *one-word* 7)
@result{} #.(SB-SYS:INT-SAP #X00600457)
CFFI> (foreign-string-to-lisp *one-word*)
@result{} "Lisp"
CFFI> (foreign-string-to-lisp *two-words*)
@result{} "Common Lisp"
@end lisp
@subheading See Also
@seealso{inc-pointer} @*
@seealso{make-pointer} @*
@seealso{pointerp} @*
@seealso{null-pointer} @*
@seealso{null-pointer-p}
@c ===================================================================
@c MAKE-POINTER
@page
@node make-pointer, mem-aptr, incf-pointer, Pointers
@heading make-pointer
@subheading Syntax
@Function{make-pointer address @res{} ptr}
@subheading Arguments and Values
@table @var
@item address
An integer.
@item ptr
A foreign pointer.
@end table
@subheading Description
The function @code{make-pointer} will return a foreign pointer
pointing to @var{address}.
@subheading Examples
@lisp
CFFI> (make-pointer 42)
@result{} #<FOREIGN-ADDRESS #x0000002A>
CFFI> (pointerp *)
@result{} T
CFFI> (pointer-address **)
@result{} 42
CFFI> (inc-pointer *** -42)
@result{} #<FOREIGN-ADDRESS #x00000000>
CFFI> (null-pointer-p *)
@result{} T
CFFI> (typep ** 'foreign-pointer)
@result{} T
@end lisp
@subheading See Also
@seealso{inc-pointer} @*
@seealso{null-pointer} @*
@seealso{null-pointer-p} @*
@seealso{pointerp} @*
@seealso{pointer-address} @*
@seealso{pointer-eq} @*
@seealso{mem-ref}
@c ===================================================================
@c MEM-APTR
@page
@node mem-aptr, mem-aref, make-pointer, Pointers
@heading mem-aptr
@subheading Syntax
@Accessor{mem-aptr ptr type &optional (index 0)}
@subheading Arguments and Values
@table @var
@item ptr
A foreign pointer.
@item type
A foreign type.
@item index
An integer.
@item new-value
A Lisp value compatible with @var{type}.
@end table
@subheading Description
The @code{mem-aptr} function finds the pointer to an element of the array.
@lisp
(mem-aptr ptr type n)
;; @lispcmt{is identical to:}
(inc-pointer ptr (* n (foreign-type-size type)))
@end lisp
@subheading Examples
@lisp
CFFI> (with-foreign-string (str "Hello, foreign world!")
(mem-aptr str :char 6))
@result{} #.(SB-SYS:INT-SAP #X0063D4B6)
@end lisp
@c ===================================================================
@c MEM-AREF
@page
@node mem-aref, mem-ref, mem-aptr, Pointers
@heading mem-aref
@subheading Syntax
@Accessor{mem-aref ptr type &optional (index 0)}
(setf (@strong{mem-aref} @emph{ptr type &optional (index 0)) new-value})
@subheading Arguments and Values
@table @var
@item ptr
A foreign pointer.
@item type
A foreign type.
@item index
An integer.
@item new-value
A Lisp value compatible with @var{type}.
@end table
@subheading Description
The @code{mem-aref} function is similar to @code{mem-ref} but will
automatically calculate the offset from an @var{index}.
@lisp
(mem-aref ptr type n)
;; @lispcmt{is identical to:}
(mem-ref ptr type (* n (foreign-type-size type)))
@end lisp
@subheading Examples
@lisp
CFFI> (with-foreign-string (str "Hello, foreign world!")
(mem-aref str :char 6))
@result{} 32
CFFI> (code-char *)
@result{} #\Space
CFFI> (with-foreign-object (array :int 10)
(loop for i below 10
do (setf (mem-aref array :int i) (random 100)))
(loop for i below 10 collect (mem-aref array :int i)))
@result{} (22 7 22 52 69 1 46 93 90 65)
@end lisp
@subheading Compatibility Note
For compatibility with older versions of CFFI, @ref{mem-aref} will
produce a pointer for the deprecated bare structure specification, but
it is consistent with other types for the current specification form
@code{(:struct @var{structure-name})} and provides a Lisp object
translated from the structure (by default a plist). In order to obtain
the pointer, you should use the new function @ref{mem-aptr}.
@subheading See Also
@seealso{mem-ref} @*
@seealso{mem-aptr}
@c ===================================================================
@c MEM-REF
@page
@node mem-ref, null-pointer, mem-aref, Pointers
@heading mem-ref
@subheading Syntax
@Accessor{mem-ref ptr type &optional offset @res{} object}
@subheading Arguments and Values
@table @var
@item ptr
A pointer.
@item type
A foreign type.
@item offset
An integer (in byte units).
@item object
The value @var{ptr} points to.
@end table
@subheading Description
@subheading Examples
@lisp
CFFI> (with-foreign-string (ptr "Saluton")
(setf (mem-ref ptr :char 3) (char-code #\a))
(loop for i from 0 below 8
collect (code-char (mem-ref ptr :char i))))
@result{} (#\S #\a #\l #\a #\t #\o #\n #\Null)
CFFI> (setq ptr-to-int (foreign-alloc :int))
@result{} #<A Mac Pointer #x1047D0>
CFFI> (mem-ref ptr-to-int :int)
@result{} 1054619
CFFI> (setf (mem-ref ptr-to-int :int) 1984)
@result{} 1984
CFFI> (mem-ref ptr-to-int :int)
@result{} 1984
@end lisp
@subheading See Also
@seealso{mem-aref}
@c ===================================================================
@c NULL-POINTER
@page
@node null-pointer, null-pointer-p, mem-ref, Pointers
@heading null-pointer
@subheading Syntax
@Function{null-pointer @res{} pointer}
@subheading Arguments and Values
@table @var
@item pointer
A @code{NULL} pointer.
@end table
@subheading Description
The function @code{null-pointer} returns a null pointer.
@subheading Examples
@lisp
CFFI> (null-pointer)
@result{} #<A Null Mac Pointer>
CFFI> (pointerp *)
@result{} T
@end lisp
@subheading See Also
@seealso{null-pointer-p} @*
@seealso{make-pointer}
@c ===================================================================
@c NULL-POINTER-P
@page
@node null-pointer-p, pointerp, null-pointer, Pointers
@heading null-pointer-p
@subheading Syntax
@Function{null-pointer-p ptr @res{} boolean}
@subheading Arguments and Values
@table @var
@item ptr
A foreign pointer that may be a null pointer.
@item boolean
@code{T} or @code{NIL}.
@end table
@subheading Description
The function @code{null-pointer-p} returns true if @var{ptr} is a null
pointer and false otherwise.
@subheading Examples
@lisp
CFFI> (null-pointer-p (null-pointer))
@result{} T
@end lisp
@lisp
(defun contains-str-p (big little)
(not (null-pointer-p
(foreign-funcall "strstr" :string big :string little :pointer))))
CFFI> (contains-str-p "Popcorns" "corn")
@result{} T
CFFI> (contains-str-p "Popcorns" "salt")
@result{} NIL
@end lisp
@subheading See Also
@seealso{null-pointer} @*
@seealso{pointerp}
@c ===================================================================
@c POINTERP
@page
@node pointerp, pointer-address, null-pointer-p, Pointers
@heading pointerp
@subheading Syntax
@Function{pointerp ptr @res{} boolean}
@subheading Arguments and Values
@table @var
@item ptr
An object that may be a foreign pointer.
@item boolean
@code{T} or @code{NIL}.
@end table
@subheading Description
The function @code{pointerp} returns true if @var{ptr} is a foreign
pointer and false otherwise.
@subheading Implementation-specific Notes
In Allegro CL, foreign pointers are integers thus in this
implementation @code{pointerp} will return true for any ordinary integer.
@subheading Examples
@lisp
CFFI> (foreign-alloc 32)
@result{} #<A Mac Pointer #x102D20>
CFFI> (pointerp *)
@result{} T
CFFI> (pointerp "this is not a pointer")
@result{} NIL
@end lisp
@subheading See Also
@seealso{make-pointer}
@seealso{null-pointer-p}
@c ===================================================================
@c POINTER-ADDRESS
@page
@node pointer-address, pointer-eq, pointerp, Pointers
@heading pointer-address
@subheading Syntax
@Function{pointer-address ptr @res{} address}
@subheading Arguments and Values
@table @var
@item ptr
A foreign pointer.
@item address
An integer.
@end table
@subheading Description
The function @code{pointer-address} will return the @var{address} of
a foreign pointer @var{ptr}.
@subheading Examples
@lisp
CFFI> (pointer-address (null-pointer))
@result{} 0
CFFI> (pointer-address (make-pointer 123))
@result{} 123
@end lisp
@subheading See Also
@seealso{make-pointer} @*
@seealso{inc-pointer} @*
@seealso{null-pointer} @*
@seealso{null-pointer-p} @*
@seealso{pointerp} @*
@seealso{pointer-eq} @*
@seealso{mem-ref}
@c ===================================================================
@c POINTER-EQ
@page
@node pointer-eq, with-foreign-object, pointer-address, Pointers
@heading pointer-eq
@subheading Syntax
@Function{pointer-eq ptr1 ptr2 @res{} boolean}
@subheading Arguments and Values
@table @var
@item ptr1
@itemx ptr2
A foreign pointer.
@item boolean
@code{T} or @code{NIL}.
@end table
@subheading Description
The function @code{pointer-eq} returns true if @var{ptr1} and
@var{ptr2} point to the same memory address and false otherwise.
@subheading Implementation-specific Notes
The representation of foreign pointers varies across the various Lisp
implementations as does the behaviour of the built-in Common Lisp
equality predicates. Comparing two pointers that point to the same
address with @code{EQ} Lisps will return true on some Lisps, others require
more general predicates like @code{EQL} or @code{EQUALP} and finally
some will return false using any of these predicates. Therefore, for
portability, you should use @code{POINTER-EQ}.
@subheading Examples
This is an example using @acronym{SBCL}, see the
implementation-specific notes above.
@lisp
CFFI> (eql (null-pointer) (null-pointer))
@result{} NIL
CFFI> (pointer-eq (null-pointer) (null-pointer))
@result{} T
@end lisp
@subheading See Also
@seealso{inc-pointer}
@c ===================================================================
@c WITH-FOREIGN-OBJECT
@page
@node with-foreign-object, with-foreign-pointer, pointer-eq, Pointers
@heading with-foreign-object, with-foreign-objects
@subheading Syntax
@Macro{with-foreign-object (var type &optional count) &body body}
@anchor{with-foreign-objects}
@Macro{with-foreign-objects (bindings) &body body}
bindings ::= @{(var type &optional count)@}*
@subheading Arguments and Values
@table @var
@item var
A symbol.
@item type
A foreign type, evaluated.
@item count
An integer.
@end table
@subheading Description
The macros @code{with-foreign-object} and @code{with-foreign-objects}
bind @var{var} to a pointer to @var{count} newly allocated objects
of type @var{type} during @var{body}. The buffer has dynamic extent
and may be stack allocated if supported by the host Lisp.
@subheading Examples
@lisp
CFFI> (with-foreign-object (array :int 10)
(dotimes (i 10)
(setf (mem-aref array :int i) (random 100)))
(loop for i below 10
collect (mem-aref array :int i)))
@result{} (22 7 22 52 69 1 46 93 90 65)
@end lisp
@subheading See Also
@seealso{foreign-alloc}
@c ===================================================================
@c WITH-FOREIGN-POINTER
@page
@node with-foreign-pointer, , with-foreign-object, Pointers
@heading with-foreign-pointer
@subheading Syntax
@Macro{with-foreign-pointer (var size &optional size-var) &body body}
@subheading Arguments and Values
@table @var
@item var
@itemx size-var
A symbol.
@item size
An integer.
@item body
A list of forms to be executed.
@end table
@subheading Description
The @code{with-foreign-pointer} macro, binds @var{var} to @var{size}
bytes of foreign memory during @var{body}. The pointer in @var{var}
is invalid beyond the dynamic extend of @var{body} and may be
stack-allocated if supported by the implementation.
If @var{size-var} is supplied, it will be bound to @var{size} during
@var{body}.
@subheading Examples
@lisp
CFFI> (with-foreign-pointer (string 4 size)
(setf (mem-ref string :char (1- size)) 0)
(lisp-string-to-foreign "Popcorns" string size)
(loop for i from 0 below size
collect (code-char (mem-ref string :char i))))
@result{} (#\P #\o #\p #\Null)
@end lisp
@subheading See Also
@seealso{foreign-alloc} @*
@seealso{foreign-free}
@c ===================================================================
@c CHAPTER: Strings
@node Strings, Variables, Pointers, Top
@chapter Strings
As with many languages, Lisp and C have special support for logical
arrays of characters, going so far as to give them a special name,
``strings''. In that spirit, @cffi{} provides special support for
translating between Lisp and C strings.
The @code{:string} type and the symbols related below also serve as an
example of what you can do portably with @cffi{}; were it not
included, you could write an equally functional @file{strings.lisp}
without referring to any implementation-specific symbols.
@menu
Dictionary
* *default-foreign-encoding*::
* foreign-string-alloc::
* foreign-string-free::
* foreign-string-to-lisp::
* lisp-string-to-foreign::
* with-foreign-string::
* with-foreign-strings::
* with-foreign-pointer-as-string::
@end menu
@c ===================================================================
@c *DEFAULT-FOREIGN-ENCODING*
@page
@node *default-foreign-encoding*, foreign-string-alloc, Strings, Strings
@heading *default-foreign-encoding*
@subheading Syntax
@Variable{*default-foreign-encoding*}
@subheading Value type
A keyword.
@subheading Initial value
@code{:utf-8}
@subheading Description
This special variable holds the default foreign encoding.
@subheading Examples
@lisp
CFFI> *default-foreign-encoding*
:utf-8
CFFI> (foreign-funcall "strdup" (:string :encoding :utf-16) "foo" :string)
"f"
CFFI> (let ((*default-foreign-encoding* :utf-16))
(foreign-funcall "strdup" (:string :encoding :utf-16) "foo" :string))
"foo"
@end lisp
@subheading See also
@seealso{Other Types} (@code{:string} type) @*
@seealso{foreign-string-alloc} @*
@seealso{foreign-string-to-lisp} @*
@seealso{lisp-string-to-foreign} @*
@seealso{with-foreign-string} @*
@seealso{with-foreign-pointer-as-string}
@c ===================================================================
@c FOREIGN-STRING-ALLOC
@page
@node foreign-string-alloc, foreign-string-free, *default-foreign-encoding*, Strings
@heading foreign-string-alloc
@subheading Syntax
@Function{foreign-string-alloc string &key encoding null-terminated-p @
start end @res{} pointer}
@subheading Arguments and Values
@table @emph
@item @var{string}
A Lisp string.
@item @var{encoding}
Foreign encoding. Defaults to @code{*default-foreign-encoding*}.
@item @var{null-terminated-p}
Boolean, defaults to true.
@item @var{start}, @var{end}
Bounding index designators of @var{string}. 0 and @code{nil}, by
default.
@item @var{pointer}
A pointer to the newly allocated foreign string.
@end table
@subheading Description
The @code{foreign-string-alloc} function allocates foreign memory
holding a copy of @var{string} converted using the specified
@var{encoding}. @var{Start} specifies an offset into @var{string} and
@var{end} marks the position following the last element of the foreign
string.
This string must be freed with @code{foreign-string-free}.
If @var{null-terminated-p} is false, the string will not be
null-terminated.
@subheading Examples
@lisp
CFFI> (defparameter *str* (foreign-string-alloc "Hello, foreign world!"))
@result{} #<FOREIGN-ADDRESS #x00400560>
CFFI> (foreign-funcall "strlen" :pointer *str* :int)
@result{} 21
@end lisp
@subheading See Also
@seealso{foreign-string-free} @*
@seealso{with-foreign-string}
@c @seealso{:string}
@c ===================================================================
@c FOREIGN-STRING-FREE
@page
@node foreign-string-free, foreign-string-to-lisp, foreign-string-alloc, Strings
@heading foreign-string-free
@subheading Syntax
@Function{foreign-string-free pointer}
@subheading Arguments and Values
@table @var
@item pointer
A pointer to a string allocated by @code{foreign-string-alloc}.
@end table
@subheading Description
The @code{foreign-string-free} function frees a foreign string
allocated by @code{foreign-string-alloc}.
@subheading Examples
@subheading See Also
@seealso{foreign-string-alloc}
@c ===================================================================
@c FOREIGN-STRING-TO-LISP
@page
@node foreign-string-to-lisp, lisp-string-to-foreign, foreign-string-free, Strings
@heading foreign-string-to-lisp
@subheading Syntax
@Function{foreign-string-to-lisp ptr &key offset count max-chars @
encoding @res{} string}
@subheading Arguments and Values
@table @var
@item ptr
A pointer.
@item offset
An integer greater than or equal to 0. Defauls to 0.
@item count
Either @code{nil} (the default), or an integer greater than or equal to 0.
@item max-chars
An integer greater than or equal to 0.
@code{(1- array-total-size-limit)}, by default.
@item encoding
Foreign encoding. Defaults to @code{*default-foreign-encoding*}.
@item string
A Lisp string.
@end table
@subheading Description
The @code{foreign-string-to-lisp} function converts at most
@var{count} octets from @var{ptr} into a Lisp string, using the
defined @var{encoding}.
If @var{count} is @code{nil} (the default), characters are copied
until @var{max-chars} is reached or a @code{NULL} character is found.
If @var{ptr} is a null pointer, returns @code{nil}.
Note that the @code{:string} type will automatically convert between
Lisp strings and foreign strings.
@subheading Examples
@lisp
CFFI> (foreign-funcall "getenv" :string "HOME" :pointer)
@result{} #<FOREIGN-ADDRESS #xBFFFFFD5>
CFFI> (foreign-string-to-lisp *)
@result{} "/Users/luis"
@end lisp
@subheading See Also
@seealso{lisp-string-to-foreign} @*
@seealso{foreign-string-alloc}
@c @seealso{:string}
@c ===================================================================
@c LISP-STRING-TO-FOREIGN
@page
@node lisp-string-to-foreign, with-foreign-string, foreign-string-to-lisp, Strings
@heading lisp-string-to-foreign
@subheading Syntax
@Function{lisp-string-to-foreign string buffer bufsize &key start @
end offset encoding @res{} buffer}
@subheading Arguments and Values
@table @emph
@item @var{string}
A Lisp string.
@item @var{buffer}
A foreign pointer.
@item @var{bufsize}
An integer.
@item @var{start}, @var{end}
Bounding index designators of @var{string}. 0 and @code{nil}, by
default.
@item @var{offset}
An integer greater than or equal to 0. Defauls to 0.
@item @var{encoding}
Foreign encoding. Defaults to @code{*default-foreign-encoding*}.
@end table
@subheading Description
The @code{lisp-string-to-foreign} function copies at most
@var{bufsize}-1 octets from a Lisp @var{string} using the specified
@var{encoding} into @var{buffer}+@var{offset}. The foreign string will
be null-terminated.
@var{Start} specifies an offset into @var{string} and
@var{end} marks the position following the last element of the foreign
string.
@subheading Examples
@lisp
CFFI> (with-foreign-pointer-as-string (str 255)
(lisp-string-to-foreign "Hello, foreign world!" str 6))
@result{} "Hello"
@end lisp
@subheading See Also
@seealso{foreign-string-alloc} @*
@seealso{foreign-string-to-lisp} @*
@seealso{with-foreign-pointer-as-string}
@c ===================================================================
@c WITH-FOREIGN-STRING
@page
@node with-foreign-string, with-foreign-pointer-as-string, lisp-string-to-foreign, Strings
@heading with-foreign-string, with-foreign-strings
@subheading Syntax
@Macro{with-foreign-string (var-or-vars string &rest args) &body body}
@anchor{with-foreign-strings}
@Macro{with-foreign-strings (bindings) &body body}
var-or-vars ::= var | (var &optional octet-size-var)
bindings ::= @{(var-or-vars string &rest args)@}*
@subheading Arguments and Values
@table @emph
@item @var{var}, @var{byte-size-var}
A symbol.
@item @var{string}
A Lisp string.
@item @var{body}
A list of forms to be executed.
@end table
@subheading Description
The @code{with-foreign-string} macro will bind @var{var} to a newly
allocated foreign string containing @var{string}. @var{Args} is passed
to the underlying @code{foreign-string-alloc} call.
If @var{octet-size-var} is provided, it will be bound the length of
foreign string in octets including the null terminator.
@subheading Examples
@lisp
CFFI> (with-foreign-string (foo "12345")
(foreign-funcall "strlen" :pointer foo :int))
@result{} 5
CFFI> (let ((array (coerce #(84 117 114 97 110 103 97)
'(array (unsigned-byte 8)))))
(with-foreign-string (foreign-string array)
(foreign-string-to-lisp foreign-string)))
@result{} "Turanga"
@end lisp
@subheading See Also
@seealso{foreign-string-alloc} @*
@seealso{with-foreign-pointer-as-string}
@c ===================================================================
@c WITH-FOREIGN-POINTER-AS-STRING
@page
@node with-foreign-pointer-as-string, , with-foreign-string, Strings
@heading with-foreign-pointer-as-string
@subheading Syntax
@Macro{with-foreign-pointer-as-string (var size &optional size-var @
&rest args) &body body @res{} string}
@subheading Arguments and Values
@table @var
@item var
A symbol.
@item string
A Lisp string.
@item body
List of forms to be executed.
@end table
@subheading Description
The @code{with-foreign-pointer-as-string} macro is similar to
@code{with-foreign-pointer} except that @var{var} is used as the
returned value of an implicit @code{progn} around @var{body}, after
being converted to a Lisp string using the provided @var{args}.
@subheading Examples
@lisp
CFFI> (with-foreign-pointer-as-string (str 6 str-size :encoding :ascii)
(lisp-string-to-foreign "Hello, foreign world!" str str-size))
@result{} "Hello"
@end lisp
@subheading See Also
@seealso{foreign-string-alloc} @*
@seealso{with-foreign-string}
@c ===================================================================
@c CHAPTER: Variables
@node Variables, Functions, Strings, Top
@chapter Variables
@menu
Dictionary
* defcvar::
* get-var-pointer::
@end menu
@c ===================================================================
@c DEFCVAR
@page
@node defcvar, get-var-pointer, Variables, Variables
@heading defcvar
@subheading Syntax
@Macro{defcvar name-and-options type &optional documentation @res{} lisp-name}
@var{name-and-options} ::= name | (name &key read-only (library :default)) @*
@var{name} ::= lisp-name [foreign-name] | foreign-name [lisp-name]
@subheading Arguments and Values
@table @var
@item foreign-name
A string denoting a foreign function.
@item lisp-name
A symbol naming the Lisp function to be created.
@item type
A foreign type.
@item read-only
A boolean.
@item documentation
A Lisp string; not evaluated.
@end table
@subheading Description
The @code{defcvar} macro defines a symbol macro @var{lisp-name} that looks
up @var{foreign-name} and dereferences it acording to @var{type}. It
can also be @code{setf}ed, unless @var{read-only} is true, in which
case an error will be signaled.
When one of @var{lisp-name} or @var{foreign-name} is omitted, the
other is automatically derived using the following rules:
@itemize
@item
Foreign names are converted to Lisp names by uppercasing, replacing
underscores with hyphens, and wrapping around asterisks.
@item
Lisp names are converted to foreign names by lowercasing, replacing
hyphens with underscores, and removing asterisks, if any.
@end itemize
@subheading Examples
@lisp
CFFI> (defcvar "errno" :int)
@result{} *ERRNO*
CFFI> (foreign-funcall "strerror" :int *errno* :string)
@result{} "Inappropriate ioctl for device"
CFFI> (setf *errno* 1)
@result{} 1
CFFI> (foreign-funcall "strerror" :int *errno* :string)
@result{} "Operation not permitted"
@end lisp
Trying to modify a read-only foreign variable:
@lisp
CFFI> (defcvar ("errno" +error-number+ :read-only t) :int)
@result{} +ERROR-NUMBER+
CFFI> (setf +error-number+ 12)
;; @lispcmt{@error{} Trying to modify read-only foreign var: +ERROR-NUMBER+.}
@end lisp
@emph{Note that accessing @code{errno} this way won't work with every
implementation of the C standard library.}
@subheading See Also
@seealso{get-var-pointer}
@c ===================================================================
@c GET-VAR-POINTER
@page
@node get-var-pointer, , defcvar, Variables
@heading get-var-pointer
@subheading Syntax
@Function{get-var-pointer symbol @res{} pointer}
@subheading Arguments and Values
@table @var
@item symbol
A symbol denoting a foreign variable defined with @code{defcvar}.
@item pointer
A foreign pointer.
@end table
@subheading Description
The function @code{get-var-pointer} will return a @var{pointer} to the
foreign global variable @var{symbol} previously defined with
@code{defcvar}.
@subheading Examples
@lisp
CFFI> (defcvar "errno" :int :read-only t)
@result{} *ERRNO*
CFFI> *errno*
@result{} 25
CFFI> (get-var-pointer '*errno*)
@result{} #<A Mac Pointer #xA0008130>
CFFI> (mem-ref * :int)
@result{} 25
@end lisp
@subheading See Also
@seealso{defcvar}
@c ===================================================================
@c CHAPTER: Functions
@node Functions, Libraries, Variables, Top
@chapter Functions
@menu
@c * Defining Foreign Functions::
@c * Calling Foreign Functions::
Dictionary
* defcfun::
* foreign-funcall::
* foreign-funcall-pointer::
* foreign-funcall-varargs::
* foreign-funcall-pointer-varargs::
* translate-camelcase-name::
* translate-name-from-foreign::
* translate-name-to-foreign::
* translate-underscore-separated-name::
@end menu
@c @node Calling Foreign Functions
@c @section Calling Foreign Functions
@c @node Defining Foreign Functions
@c @section Defining Foreign Functions
@c ===================================================================
@c DEFCFUN
@page
@node defcfun, foreign-funcall, Functions, Functions
@heading defcfun
@subheading Syntax
@Macro{defcfun name-and-options return-type &body [docstring] arguments [&rest] @
@res{} lisp-name}
@var{name-and-options} ::= @var{name} | (@var{name} &key @var{library} @var{convention}) @*
@var{name} ::= @var{lisp-name} [@var{foreign-name}] | @var{foreign-name} [@var{lisp-name}] @*
@var{arguments} ::= @{ (@var{arg-name} @var{arg-type}) @}* @*
@subheading Arguments and Values
@table @var
@item foreign-name
A string denoting a foreign function.
@item lisp-name
A symbol naming the Lisp function to be created.
@item arg-name
A symbol.
@item return-type
@itemx arg-type
A foreign type.
@item convention
One of @code{:cdecl} (default) or @code{:stdcall}.
@item library
A symbol designating a foreign library.
@item docstring
A documentation string.
@end table
@subheading Description
The @code{defcfun} macro provides a declarative interface for defining
Lisp functions that call foreign functions.
When one of @var{lisp-name} or @var{foreign-name} is omitted, the
other is automatically derived using the following rules:
@itemize
@item
Foreign names are converted to Lisp names by uppercasing and replacing
underscores with hyphens.
@item
Lisp names are converted to foreign names by lowercasing and replacing
hyphens with underscores.
@end itemize
If you place the symbol @code{&rest} in the end of the argument list
after the fixed arguments, @code{defcfun} will treat the foreign
function as a @strong{variadic function}. The variadic arguments
should be passed in a way similar to what @code{foreign-funcall} would
expect. Unlike @code{foreign-funcall} though, @code{defcfun} will take
care of doing argument promotion. Note that in this case
@code{defcfun} will generate a Lisp @emph{macro} instead of a
function and will only work for Lisps that support
@code{foreign-funcall.}
If a foreign structure is to be passed or returned by value (that is,
the type is of the form @code{(:struct ...)}), then the cffi-libffi system
must be loaded, which in turn depends on
@uref{http://sourceware.org/libffi/,libffi}, including the header files.
Failure to load that system will result in an error.
Variadic functions cannot at present accept or return structures by
value.
@subheading Examples
@lisp
(defcfun "strlen" :int
"Calculate the length of a string."
(n :string))
CFFI> (strlen "123")
@result{} 3
@end lisp
@lisp
(defcfun ("abs" c-abs) :int (n :int))
CFFI> (c-abs -42)
@result{} 42
@end lisp
Function without arguments:
@lisp
(defcfun "rand" :int)
CFFI> (rand)
@result{} 1804289383
@end lisp
Variadic function example:
@lisp
(defcfun "sprintf" :int
(str :pointer)
(control :string)
&rest)
CFFI> (with-foreign-pointer-as-string (s 100)
(sprintf s "%c %d %.2f %s" :char 90 :short 42 :float pi
:string "super-locrian"))
@result{} "A 42 3.14 super-locrian"
@end lisp
@subheading See Also
@seealso{foreign-funcall} @*
@seealso{foreign-funcall-pointer} @*
@seealso{foreign-funcall-varargs} @*
@seealso{foreign-funcall-pointer-varargs}
@c ===================================================================
@c FOREIGN-FUNCALL
@page
@node foreign-funcall, foreign-funcall-pointer, defcfun, Functions
@heading foreign-funcall
@subheading Syntax
@Macro{foreign-funcall name-and-options &rest arguments @res{} return-value}
@var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
@var{name-and-options} ::= @var{name} | (@var{name} &key @var{library} @var{convention}) @*
@subheading Arguments and Values
@table @var
@item name
A Lisp string.
@item arg-type
A foreign type.
@item arg
An argument of type @var{arg-type}.
@item return-type
A foreign type, @code{:void} by default.
@item return-value
A lisp object.
@item library
A lisp symbol; not evaluated.
@item convention
One of @code{:cdecl} (default) or @code{:stdcall}.
@end table
@subheading Description
The @code{foreign-funcall} macro is the main primitive for calling
foreign functions.
If a foreign structure is to be passed or returned by value (that is,
the type is of the form @code{(:struct ...)}), then the cffi-libffi system
must be loaded, which in turn depends on
@uref{http://sourceware.org/libffi/,libffi}, including the header files.
Failure to load that system will result in an error.
Variadic functions cannot at present accept or return structures by
value.
@emph{Note: The return value of foreign-funcall on functions with a
:void return type is still undefined.}
@subheading Implementation-specific Notes
@itemize
@item
Corman Lisp does not support @code{foreign-funcall}. On
implementations that @strong{don't} support @code{foreign-funcall}
@code{cffi-sys::no-foreign-funcall} will be present in
@code{*features*}. Note: in these Lisps you can still use the
@code{defcfun} interface.
@end itemize
@subheading Examples
@lisp
CFFI> (foreign-funcall "strlen" :string "foo" :int)
@result{} 3
@end lisp
Given the C code:
@example
void print_number(int n)
@{
printf("N: %d\n", n);
@}
@end example
@lisp
CFFI> (foreign-funcall "print_number" :int 123456)
@print{} N: 123456
@result{} NIL
@end lisp
@noindent
Or, equivalently:
@lisp
CFFI> (foreign-funcall "print_number" :int 123456 :void)
@print{} N: 123456
@result{} NIL
@end lisp
@lisp
CFFI> (foreign-funcall "printf" :string (format nil "%s: %d.~%")
:string "So long and thanks for all the fish"
:int 42 :int)
@print{} So long and thanks for all the fish: 42.
@result{} 41
@end lisp
@subheading See Also
@seealso{defcfun} @*
@seealso{foreign-funcall-pointer}
@c ===================================================================
@c FOREIGN-FUNCALL-POINTER
@page
@node foreign-funcall-pointer, foreign-funcall-varargs, foreign-funcall, Functions
@heading foreign-funcall-pointer
@subheading Syntax
@Macro{foreign-funcall-pointer pointer options &rest arguments @res{} return-value}
@var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
@var{options} ::= (&key @var{convention}) @*
@subheading Arguments and Values
@table @var
@item pointer
A foreign pointer.
@item arg-type
A foreign type.
@item arg
An argument of type @var{arg-type}.
@item return-type
A foreign type, @code{:void} by default.
@item return-value
A lisp object.
@item convention
One of @code{:cdecl} (default) or @code{:stdcall}.
@end table
@subheading Description
The @code{foreign-funcall} macro is the main primitive for calling
foreign functions.
@emph{Note: The return value of foreign-funcall on functions with a
:void return type is still undefined.}
@subheading Implementation-specific Notes
@itemize
@item
Corman Lisp does not support @code{foreign-funcall}. On
implementations that @strong{don't} support @code{foreign-funcall}
@code{cffi-sys::no-foreign-funcall} will be present in
@code{*features*}. Note: in these Lisps you can still use the
@code{defcfun} interface.
@end itemize
@subheading Examples
@lisp
CFFI> (foreign-funcall-pointer (foreign-symbol-pointer "abs") ()
:int -42 :int)
@result{} 42
@end lisp
@subheading See Also
@seealso{defcfun} @*
@seealso{foreign-funcall}
@c ===================================================================
@c FOREIGN-FUNCALL-VARARGS
@page
@node foreign-funcall-varargs, foreign-funcall-pointer-varargs, foreign-funcall-pointer, Functions
@heading foreign-funcall-varargs
@subheading Syntax
@Macro{foreign-funcall-varargs name-and-options (fixed-arguments) &rest arguments @res{} return-value}
@var{fixed-arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
@var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
@var{name-and-options} ::= @var{name} | (@var{name} &key @var{library} @var{convention}) @*
@subheading Arguments and Values
@table @var
@item name
A Lisp string.
@item arg-type
A foreign type.
@item arg
An argument of type @var{arg-type}.
@item return-type
A foreign type, @code{:void} by default.
@item return-value
A lisp object.
@item library
A lisp symbol; not evaluated.
@item convention
One of @code{:cdecl} (default) or @code{:stdcall}.
@end table
@subheading Description
The @code{foreign-funcall-varargs} macro is the main primitive for
calling foreign variadic functions. It behaves similarily to
@code{foreign-funcall} except @code{fixed-arguments} are distinguished
from the remaining arguments.
@subheading Examples
@lisp
CFFI> (with-foreign-pointer-as-string (s 100)
(setf (mem-ref s :char) 0)
(foreign-funcall-varargs
"sprintf" (:pointer s :string) "%.2f")
:double (coerce pi 'double-float) :int))
@result{} 3.14
@end lisp
@c ===================================================================
@c FOREIGN-FUNCALL-POINTER-VARARGS
@page
@node foreign-funcall-pointer-varargs, translate-camelcase-name, foreign-funcall-varargs, Functions
@heading foreign-funcall-pointer-varargs
@subheading Syntax
@Macro{foreign-funcall-pointer-varargs pointer options (fixed-arguments) &rest arguments @res{} return-value}
@var{fixed-arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
@var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
@var{options} ::= (&key @var{convention}) @*
@subheading Arguments and Values
@table @var
@item pointer
A foreign pointer.
@item arg-type
A foreign type.
@item arg
An argument of type @var{arg-type}.
@item return-type
A foreign type, @code{:void} by default.
@item return-value
A lisp object.
@item convention
One of @code{:cdecl} (default) or @code{:stdcall}.
@end table
@subheading Description
The @code{foreign-funcall-pointer-varargs} macro is the main primitive
for calling foreign variadic functions. It behaves similarily to
@code{foreign-funcall-pointer} except @code{fixed-arguments} are
distinguished from the remaining arguments.
@subheading Examples
@lisp
CFFI> (with-foreign-pointer-as-string (s 100)
(setf (mem-ref s :char) 0)
(foreign-funcall-pointer-varargs
(foreign-symbol-pointer "sprintf") () (:pointer s :string "%.2f")
:double (coerce pi 'double-float) :int))
@result{} 3.14
@end lisp
@c ===================================================================
@c TRANSLATE-CAMELCASE-NAME
@page
@node translate-camelcase-name, translate-name-from-foreign, foreign-funcall-pointer-varargs, Functions
@heading translate-camelcase-name
@subheading Syntax
@Function{translate-camelcase-name name &key upper-initial-p special-words @res{} return-value}
@subheading Arguments and Values
@table @var
@item name
Either a symbol or a string.
@item upper-initial-p
A generalized boolean.
@item special words
A list of strings.
@item return-value
If @var{name} is a symbol, this is a string, and vice versa.
@end table
@subheading Description
@code{translate-camelcase-name} is a helper function for
specializations of @code{translate-name-from-foreign} and
@code{translate-name-to-foreign}. It handles the common case of
converting between foreign camelCase names and lisp
names. @var{upper-initial-p} indicates whether the first letter of the
foreign name should be uppercase. @var{special-words} is a list of
strings that should be treated atomically in translation. This list is
case-sensitive.
@subheading Examples
@lisp
CFFI> (translate-camelcase-name some-xml-function)
@result{} "someXmlFunction"
CFFI> (translate-camelcase-name some-xml-function :upper-initial-p t)
@result{} "SomeXmlFunction"
CFFI> (translate-camelcase-name some-xml-function :special-words '("XML"))
@result{} "someXMLFunction"
CFFI> (translate-camelcase-name "someXMLFunction")
@result{} SOME-X-M-L-FUNCTION
CFFI> (translate-camelcase-name "someXMLFunction" :special-words '("XML"))
@result{} SOME-XML-FUNCTION
@end lisp
@subheading See Also
@seealso{translate-name-from-foreign} @*
@seealso{translate-name-to-foreign} @*
@seealso{translate-underscore-separated-name}
@c ===================================================================
@c TRANSLATE-NAME-FROM-FOREIGN
@page
@node translate-name-from-foreign, translate-name-to-foreign, translate-camelcase-name, Functions
@heading translate-name-from-foreign
@subheading Syntax
@Function{translate-name-from-foreign foreign-name package &optional varp @res{} symbol}
@subheading Arguments and Values
@table @var
@item foreign-name
A string denoting a foreign function.
@item package
A Lisp package
@item varp
A generalized boolean.
@item symbol
The Lisp symbol to be used a function name.
@end table
@subheading Description
@code{translate-name-from-foreign} is used by @ref{defcfun} to handle
the conversion of foreign names to lisp names. By default, it
translates using @ref{translate-underscore-separated-name}. However,
you can create specialized methods on this function to make
translating more closely match the foreign library's naming
conventions.
Specialize @var{package} on some package. This allows other packages
to load libraries with different naming conventions.
@subheading Examples
@lisp
CFFI> (defcfun "someXmlFunction" ...)
@result{} SOMEXMLFUNCTION
CFFI> (defmethod translate-name-from-foreign ((spec string)
(package (eql *package*))
&optional varp)
(let ((name (translate-camelcase-name spec)))
(if varp (intern (format nil "*~a*" name)) name)))
@result{} #<STANDARD-METHOD TRANSLATE-NAME-FROM-FOREIGN (STRING (EQL #<Package "SOME-PACKAGE">))>
CFFI> (defcfun "someXmlFunction" ...)
@result{} SOME-XML-FUNCTION
@end lisp
@subheading See Also
@seealso{defcfun} @*
@seealso{translate-camelcase-name} @*
@seealso{translate-name-to-foreign} @*
@seealso{translate-underscore-separated-name}
@c ===================================================================
@c TRANSLATE-NAME-TO-FOREIGN
@page
@node translate-name-to-foreign, translate-underscore-separated-name, translate-name-from-foreign, Functions
@heading translate-name-to-foreign
@subheading Syntax
@Function{translate-name-to-foreign lisp-name package &optional varp @res{} string}
@subheading Arguments and Values
@table @var
@item lisp-name
A symbol naming the Lisp function to be created.
@item package
A Lisp package
@item varp
A generalized boolean.
@item string
The string representing the foreign function name.
@end table
@subheading Description
@code{translate-name-to-foreign} is used by @ref{defcfun} to handle
the conversion of lisp names to foreign names. By default, it
translates using @ref{translate-underscore-separated-name}. However,
you can create specialized methods on this function to make
translating more closely match the foreign library's naming
conventions.
Specialize @var{package} on some package. This allows other packages
to load libraries with different naming conventions.
@subheading Examples
@lisp
CFFI> (defcfun some-xml-function ...)
@result{} "some_xml_function"
CFFI> (defmethod translate-name-to-foreign ((spec symbol)
(package (eql *package*))
&optional varp)
(let ((name (translate-camelcase-name spec)))
(if varp (subseq name 1 (1- (length name))) name)))
@result{} #<STANDARD-METHOD TRANSLATE-NAME-TO-FOREIGN (STRING (EQL #<Package "SOME-PACKAGE">))>
CFFI> (defcfun some-xml-function ...)
@result{} "someXmlFunction"
@end lisp
@subheading See Also
@seealso{defcfun} @*
@seealso{translate-camelcase-name} @*
@seealso{translate-name-from-foreign} @*
@seealso{translate-underscore-separated-name}
@c ===================================================================
@c TRANSLATE-UNDERSCORE-SEPARATED-NAME
@page
@node translate-underscore-separated-name, , translate-name-to-foreign, Functions
@heading translate-underscore-separated-name
@subheading Syntax
@Function{translate-underscore-separated-name name @res{} return-value}
@subheading Arguments and Values
@table @var
@item name
Either a symbol or a string.
@item return-value
If @var{name} is a symbol, this is a string, and vice versa.
@end table
@subheading Description
@code{translate-underscore-separated-name} is a helper function for
specializations of @ref{translate-name-from-foreign} and
@ref{translate-name-to-foreign}. It handles the common case of
converting between foreign underscore_separated names and lisp names.
@subheading Examples
@lisp
CFFI> (translate-underscore-separated-name some-xml-function)
@result{} "some_xml_function"
CFFI> (translate-camelcase-name "some_xml_function")
@result{} SOME-XML-FUNCTION
@end lisp
@subheading See Also
@seealso{translate-name-from-foreign} @*
@seealso{translate-name-to-foreign} @*
@seealso{translate-camelcase-name}
@c ===================================================================
@c CHAPTER: Libraries
@node Libraries, Callbacks, Functions, Top
@chapter Libraries
@menu
* Defining a library::
* Library definition style::
Dictionary
* close-foreign-library:: Close a foreign library.
* *darwin-framework-directories*:: Search path for Darwin frameworks.
* define-foreign-library:: Explain how to load a foreign library.
* *foreign-library-directories*:: Search path for shared libraries.
* load-foreign-library:: Load a foreign library.
* load-foreign-library-error:: Signalled on failure of its namesake.
* use-foreign-library:: Load a foreign library when needed.
@end menu
@node Defining a library, Library definition style, Libraries, Libraries
@section Defining a library
Almost all foreign code you might want to access exists in some kind
of shared library. The meaning of @dfn{shared library} varies among
platforms, but for our purposes, we will consider it to include
@file{.so} files on @sc{unix}, frameworks on Darwin (and derivatives
like Mac @acronym{OS X}), and @file{.dll} files on Windows.
Bringing one of these libraries into the Lisp image is normally a
two-step process.
@enumerate
@item
Describe to @cffi{} how to load the library at some future point,
depending on platform and other factors, with a
@code{define-foreign-library} top-level form.
@item
Load the library so defined with either a top-level
@code{use-foreign-library} form or by calling the function
@code{load-foreign-library}.
@end enumerate
@xref{Tutorial-Loading,, Loading foreign libraries}, for a working
example of the above two steps.
@node Library definition style, close-foreign-library, Defining a library, Libraries
@section Library definition style
Looking at the @code{libcurl} library definition presented earlier,
you may ask why we did not simply do this:
@lisp
(define-foreign-library libcurl
(t (:default "libcurl")))
@end lisp
@noindent
Indeed, this would work just as well on the computer on which I tested
the tutorial. There are a couple of good reasons to provide the
@file{.so}'s current version number, however. Namely, the versionless
@file{.so} is not packaged on most @sc{unix} systems along with the
actual, fully-versioned library; instead, it is included in the
``development'' package along with C headers and static @file{.a}
libraries.
The reason @cffi{} does not try to account for this lies in the
meaning of the version numbers. A full treatment of shared library
versions is beyond this manual's scope; see @ref{Versioning,, Library
interface versions, libtool, @acronym{GNU} Libtool}, for helpful
information for the unfamiliar. For our purposes, consider that a
mismatch between the library version with which you tested and the
installed library version may cause undefined
behavior.@footnote{Windows programmers may chafe at adding a
@sc{unix}-specific clause to @code{define-foreign-library}. Instead,
ask why the Windows solution to library incompatibility is ``include
your own version of every library you use with every program''.}
@impnote{Maybe some notes should go here about OS X, which I know
little about. --stephen}
@c ===================================================================
@c CLOSE-FOREIGN-LIBRARY
@page
@node close-foreign-library, *darwin-framework-directories*, Library definition style, Libraries
@heading close-foreign-library
@subheading Syntax
@Function{close-foreign-library library @res{} success}
@subheading Arguments and Values
@table @var
@item library
A symbol or an instance of @code{foreign-library}.
@item success
A Lisp boolean.
@end table
@subheading Description
Closes @var{library} which can be a symbol designating a library
define through @code{define-foreign-library} or an instance of
@code{foreign-library} as returned by @code{load-foreign-library}.
@c @subheading Examples
@c @xref{Tutorial-Loading,, Loading foreign libraries}.
@subheading See Also
@seealso{define-foreign-library} @*
@seealso{load-foreign-library} @*
@seealso{use-foreign-library}
@c ===================================================================
@c *DARWIN-FRAMEWORK-DIRECTORIES*
@page
@node *darwin-framework-directories*, define-foreign-library, close-foreign-library, Libraries
@heading *darwin-framework-directories*
@subheading Syntax
@Variable{*darwin-framework-directories*}
@subheading Value type
A list, in which each element is a string, a pathname, or a simple
Lisp expression.
@subheading Initial value
A list containing the following, in order: an expression corresponding
to Darwin path @file{~/Library/Frameworks/},
@code{#P"/Library/Frameworks/"}, and
@code{#P"/System/Library/Frameworks/"}.
@subheading Description
The meaning of ``simple Lisp expression'' is explained in
@ref{*foreign-library-directories*}. In contrast to that variable,
this is not a fallback search path; the default value described above
is intended to be a reasonably complete search path on Darwin systems.
@subheading Examples
@lisp
CFFI> (let ((lib (load-foreign-library '(:framework "OpenGL"))))
(foreign-library-pathname lib))
@result{} #P"/System/Library/Frameworks/OpenGL.framework/OpenGL"
@end lisp
@subheading See also
@seealso{*foreign-library-directories*} @*
@seealso{define-foreign-library}
@c ===================================================================
@c DEFINE-FOREIGN-LIBRARY
@page
@node define-foreign-library, *foreign-library-directories*, *darwin-framework-directories*, Libraries
@heading define-foreign-library
@subheading Syntax
@Macro{define-foreign-library name-and-options @{ load-clause @}* @res{} name}
name-and-options ::= name | (name &key convention search-path)
load-clause ::= (feature library &key convention search-path)
@subheading Arguments and Values
@table @var
@item name
A symbol.
@item feature
A feature expression.
@item library
A library designator.
@item convention
One of @code{:cdecl} (default) or @code{:stdcall}
@item search-path
A path or list of paths where the library will be searched if not found in
system-global directories. Paths specified in a load clause take priority over
paths specified as library option, with *foreign-library-directories* having
lowest priority.
@end table
@subheading Description
Creates a new library designator called @var{name}. The
@var{load-clause}s describe how to load that designator when passed to
@code{load-foreign-library} or @code{use-foreign-library}.
When trying to load the library @var{name}, the relevant function
searches the @var{load-clause}s in order for the first one where
@var{feature} evaluates to true. That happens for any of the
following situations:
@enumerate 1
@item
If @var{feature} is a symbol present in @code{common-lisp:*features*}.
@item
If @var{feature} is a list, depending on @code{(first @var{feature})},
a keyword:
@table @code
@item :and
All of the feature expressions in @code{(rest @var{feature})} are
true.
@item :or
At least one of the feature expressions in @code{(rest @var{feature})}
is true.
@item :not
The feature expression @code{(second @var{feature})} is not true.
@end table
@item
Finally, if @var{feature} is @code{t}, this @var{load-clause} is
picked unconditionally.
@end enumerate
Upon finding the first true @var{feature}, the library loader then
loads the @var{library}. The meaning of ``library designator'' is
described in @ref{load-foreign-library}.
Functions associated to a library defined by
@code{define-foreign-library} (e.g. through @code{defcfun}'s
@code{:library} option, will inherit the library's options. The
precedence is as follows:
@enumerate 1
@item
@code{defcfun}/@code{foreign-funcall} specific options;
@item
@var{load-clause} options;
@item
global library options (the @var{name-and-options} argument)
@end enumerate
@subheading Examples
@xref{Tutorial-Loading,, Loading foreign libraries}.
@subheading See Also
@seealso{close-foreign-library} @*
@seealso{load-foreign-library}
@c ===================================================================
@c *FOREIGN-LIBRARY-DIRECTORIES*
@page
@node *foreign-library-directories*, load-foreign-library, define-foreign-library, Libraries
@heading *foreign-library-directories*
@subheading Syntax
@Variable{*foreign-library-directories*}
@subheading Value type
A list, in which each element is a string, a pathname, or a simple
Lisp expression.
@subheading Initial value
The empty list.
@subheading Description
You should not have to use this variable.
Most, if not all, Lisps supported by @cffi{} have a reasonable default
search algorithm for foreign libraries. For example, Lisps for
@sc{unix} usually call
@uref{http://www.opengroup.org/onlinepubs/009695399/functions/dlopen.html,,
@code{dlopen(3)}}, which in turn looks in the system library
directories. Only if that fails does @cffi{} look for the named
library file in these directories, and load it from there if found.
Thus, this is intended to be a @cffi{}-only fallback to the library
search configuration provided by your operating system. For example,
if you distribute a foreign library with your Lisp package, you can
add the library's containing directory to this list and portably
expect @cffi{} to find it.
A @dfn{simple Lisp expression} is intended to provide functionality
commonly used in search paths such as
@acronym{ASDF}'s@footnote{@xref{Using asdf to load systems,,, asdf,
asdf: another system definition facility}, for information on
@code{asdf:*central-registry*}.}, and is defined recursively as
follows:@footnote{See @code{mini-eval} in @file{libraries.lisp} for
the source of this definition. As is always the case with a Lisp
@code{eval}, it's easier to understand the Lisp definition than the
english.}
@enumerate
@item
A list, whose @samp{first} is a function designator, and whose
@samp{rest} is a list of simple Lisp expressions to be evaluated and
passed to the so-designated function. The result is the result of the
function call.
@item
A symbol, whose result is its symbol value.
@item
Anything else evaluates to itself.
@end enumerate
The result of evaluating the @dfn{simple Lisp expression} should yield
a @emph{designator} for a @emph{list} of @emph{pathname designators}.
@strong{Note}: in Common Lisp, @code{#p"/foo/bar"} designates the
@emph{bar} file within the @emph{/foo} directory whereas
@code{#p"/foo/bar/"} designates the @emph{/foo/bar} directory. Keep
that in mind when customising the value of
@code{*foreign-library-directories*}.
@subheading Examples
@example
$ ls
@print{} liblibli.so libli.lisp
@end example
@noindent
In @file{libli.lisp}:
@lisp
(pushnew #P"/home/sirian/lisp/libli/" *foreign-library-directories*
:test #'equal)
(load-foreign-library '(:default "liblibli"))
@end lisp
@noindent
The following example would achieve the same effect:
@lisp
(pushnew '(merge-pathnames #p"lisp/libli/" (user-homedir-pathname))
*foreign-library-directories*
:test #'equal)
@result{} ((MERGE-PATHNAMES #P"lisp/libli/" (USER-HOMEDIR-PATHNAME)))
(load-foreign-library '(:default "liblibli"))
@end lisp
@subheading See also
@seealso{*darwin-framework-directories*} @*
@seealso{define-foreign-library}
@c ===================================================================
@c LOAD-FOREIGN-LIBRARY
@page
@node load-foreign-library, load-foreign-library-error, *foreign-library-directories*, Libraries
@heading load-foreign-library
@subheading Syntax
@Function{load-foreign-library library-designator @res{} library}
@subheading Arguments and Values
@table @var
@item library-designator
A library designator.
@item library-designator
An instance of @code{foreign-library}.
@end table
@subheading Description
Load the library indicated by @var{library-designator}. A @dfn{library
designator} is defined as follows:
@enumerate
@item
If a symbol, is considered a name previously defined with
@code{define-foreign-library}.
@item
If a string or pathname, passed as a namestring directly to the
implementation's foreign library loader. If that fails, search the
directories in @code{*foreign-library-directories*} with
@code{cl:probe-file}; if found, the absolute path is passed to the
implementation's loader.
@item
If a list, the meaning depends on @code{(first @var{library})}:
@table @code
@item :framework
The second list element is taken to be a Darwin framework name, which
is then searched in @code{*darwin-framework-directories*}, and loaded
when found.
@item :or
Each remaining list element, itself a @dfn{library designator}, is loaded in
order, until one succeeds.
@item :default
The name is transformed according to the platform's naming convention
to shared libraries, and the resultant string is loaded as a @dfn{library
designator}. For example, on @sc{unix}, the name is suffixed with
@file{.so}.
@end table
@end enumerate
If the library is already loaded it will be reloaded.
If the load fails, signal a @code{load-foreign-library-error}.
@strong{Please note:} For system libraries, you should not need to
specify the directory containing the library. Each operating system
has its own idea of a default search path, and you should rely on it
when it is reasonable.
@subheading Implementation-specific Notes
On ECL platforms where its dynamic FFI is not supported (ie. when
@code{:dffi} is not present in @code{*features*}),
@code{cffi:load-foreign-library} does not work and you must use ECL's
own @code{ffi:load-foreign-library} with a constant string argument.
@subheading Examples
@xref{Tutorial-Loading,, Loading foreign libraries}.
@subheading See Also
@seealso{close-foreign-library} @*
@seealso{*darwin-framework-directories*} @*
@seealso{define-foreign-library} @*
@seealso{*foreign-library-directories*} @*
@seealso{load-foreign-library-error} @*
@seealso{use-foreign-library}
@c ===================================================================
@c LOAD-FOREIGN-LIBRARY-ERROR
@page
@node load-foreign-library-error, use-foreign-library, load-foreign-library, Libraries
@heading load-foreign-library-error
@subheading Syntax
@Condition{load-foreign-library-error}
@subheading Class precedence list
@code{load-foreign-library-error}, @code{error},
@code{serious-condition}, @code{condition}, @code{t}
@subheading Description
Signalled when a foreign library load completely fails. The exact
meaning of this varies depending on the real conditions at work, but
almost universally, the implementation's error message is useless.
However, @cffi{} does provide the useful restarts @code{retry} and
@code{use-value}; invoke the @code{retry} restart to try loading the
foreign library again, or the @code{use-value} restart to try loading
a different foreign library designator.
@subheading See also
@seealso{load-foreign-library}
@c ===================================================================
@c USE-FOREIGN-LIBRARY
@page
@node use-foreign-library, , load-foreign-library-error, Libraries
@heading use-foreign-library
@subheading Syntax
@Macro{use-foreign-library name}
@subheading Arguments and values
@table @var
@item name
A library designator; unevaluated.
@end table
@subheading Description
@xref{load-foreign-library}, for the meaning of ``library
designator''. This is intended to be the top-level form used
idiomatically after a @code{define-foreign-library} form to go ahead
and load the library. @c ; it also sets the ``current foreign library''.
Finally, on implementations where the regular evaluation rule is
insufficient for foreign library loading, it loads it at the required
time.@footnote{Namely, @acronym{CMUCL}. See
@code{use-foreign-library} in @file{libraries.lisp} for details.}
@c current foreign library is a concept created a few hours ago as of
@c this writing. It is not actually used yet, but probably will be.
@subheading Examples
@xref{Tutorial-Loading,, Loading foreign libraries}.
@subheading See also
@seealso{load-foreign-library}
@c ===================================================================
@c CHAPTER: Callbacks
@node Callbacks, The Groveller, Libraries, Top
@chapter Callbacks
@menu
Dictionary
* callback::
* defcallback::
* get-callback::
@end menu
@c ===================================================================
@c CALLBACK
@page
@node callback, defcallback, Callbacks, Callbacks
@heading callback
@subheading Syntax
@Macro{callback symbol @res{} pointer}
@subheading Arguments and Values
@table @var
@item symbol
A symbol denoting a callback.
@item pointer
@itemx new-value
A pointer.
@end table
@subheading Description
The @code{callback} macro is analogous to the standard CL special
operator @code{function} and will return a pointer to the callback
denoted by the symbol @var{name}.
@subheading Examples
@lisp
CFFI> (defcallback sum :int ((a :int) (b :int))
(+ a b))
@result{} SUM
CFFI> (callback sum)
@result{} #<A Mac Pointer #x102350>
@end lisp
@subheading See Also
@seealso{get-callback} @*
@seealso{defcallback}
@c ===================================================================
@c DEFCALLBACK
@page
@node defcallback, get-callback, callback, Callbacks
@heading defcallback
@subheading Syntax
@Macro{defcallback name-and-options return-type arguments &body body @res{} name}
name-and-options ::= name | (name &key convention)
arguments ::= (@{ (arg-name arg-type) @}*)
@subheading Arguments and Values
@table @var
@item name
A symbol naming the callback created.
@item return-type
The foreign type for the callback's return value.
@item arg-name
A symbol.
@item arg-type
A foreign type.
@item convention
One of @code{:cdecl} (default) or @code{:stdcall}.
@end table
@subheading Description
The @code{defcallback} macro defines a Lisp function that can be called
from C. The arguments passed to this function will be converted to the
appropriate Lisp representation and its return value will be converted
to its C representation.
This Lisp function can be accessed by the @code{callback} macro or the
@code{get-callback} function.
@strong{Portability note:} @code{defcallback} will not work correctly
on some Lisps if it's not a top-level form.
@subheading Examples
@lisp
(defcfun "qsort" :void
(base :pointer)
(nmemb :int)
(size :int)
(fun-compar :pointer))
(defcallback < :int ((a :pointer) (b :pointer))
(let ((x (mem-ref a :int))
(y (mem-ref b :int)))
(cond ((> x y) 1)
((< x y) -1)
(t 0))))
CFFI> (with-foreign-object (array :int 10)
;; @lispcmt{Initialize array.}
(loop for i from 0 and n in '(7 2 10 4 3 5 1 6 9 8)
do (setf (mem-aref array :int i) n))
;; @lispcmt{Sort it.}
(qsort array 10 (foreign-type-size :int) (callback <))
;; @lispcmt{Return it as a list.}
(loop for i from 0 below 10
collect (mem-aref array :int i)))
@result{} (1 2 3 4 5 6 7 8 9 10)
@end lisp
@subheading See Also
@seealso{callback} @*
@seealso{get-callback}
@c ===================================================================
@c GET-CALLBACK
@page
@node get-callback, , defcallback, Callbacks
@heading get-callback
@subheading Syntax
@Accessor{get-callback symbol @res{} pointer}
@subheading Arguments and Values
@table @var
@item symbol
A symbol denoting a callback.
@item pointer
A pointer.
@end table
@subheading Description
This is the functional version of the @code{callback} macro. It
returns a pointer to the callback named by @var{symbol} suitable, for
example, to pass as arguments to foreign functions.
@subheading Examples
@lisp
CFFI> (defcallback sum :int ((a :int) (b :int))
(+ a b))
@result{} SUM
CFFI> (get-callback 'sum)
@result{} #<A Mac Pointer #x102350>
@end lisp
@subheading See Also
@seealso{callback} @*
@seealso{defcallback}
@c ===================================================================
@c CHAPTER: The Groveller
@node The Groveller, Limitations, Callbacks, Top
@chapter The Groveller
@cffi{}-Grovel is a tool which makes it easier to write @cffi{}
declarations for libraries that are implemented in C. That is, it
grovels through the system headers, getting information about types
and structures, so you don't have to. This is especially important
for libraries which are implemented in different ways by different
vendors, such as the @sc{unix}/@sc{posix} functions. The @cffi{}
declarations are usually quite different from platform to platform,
but the information you give to @cffi{}-Grovel is the same. Hence,
much less work is required!
If you use @acronym{ASDF}, @cffi{}-Grovel is integrated, so that it
will run automatically when your system is building. This feature was
inspired by SB-Grovel, a similar @acronym{SBCL}-specific project.
@cffi{}-Grovel can also be used without @acronym{ASDF}.
@section Building FFIs with CFFI-Grovel
@cffi{}-Grovel uses a specification file (*.lisp) describing the
features that need groveling. The C compiler is used to retrieve this
data and write a Lisp file (*.cffi.lisp) which contains the necessary
@cffi{} definitions to access the variables, structures, constants, and
enums mentioned in the specification.
@c This is most similar to the SB-Grovel package, upon which it is
@c based. Unlike SB-Grovel, we do not currently support defining
@c regular foreign functions in the specification file; those are best
@c defined in normal Lisp code.
@cffi{}-Grovel provides an @acronym{ASDF} component for handling the
necessary calls to the C compiler and resulting file management.
@c See the included CFFI-Unix package for an example of how to
@c integrate a specification file with ASDF-built packages.
@menu
* Groveller Syntax:: How grovel files should look like.
* Groveller ASDF Integration:: ASDF components for grovel files.
* Groveller Implementation Notes:: Implementation notes.
* Wrapper for Inline/Static Functions and Macros:: Wrapper
@end menu
@node Groveller Syntax, Groveller ASDF Integration, The Groveller, The Groveller
@section Specification File Syntax
The specification files are read by the normal Lisp reader, so they
have syntax very similar to normal Lisp code. In particular,
semicolon-comments and reader-macros will work as expected.
There are several forms recognized by @cffi{}-Grovel:
@deffn {Grovel Form} progn &rest forms
Processes a list of forms. Useful for conditionalizing several
forms. For example:
@end deffn
@lisp
#+freebsd
(progn
(constant (ev-enable "EV_ENABLE"))
(constant (ev-disable "EV_DISABLE")))
@end lisp
@deffn {Grovel Form} include &rest files
Include the specified files (specified as strings) in the generated C
source code.
@end deffn
@deffn {Grovel Form} in-package symbol
Set the package to be used for the final Lisp output.
@end deffn
@deffn {Grovel Form} ctype lisp-name size-designator
Define a @cffi{} foreign type for the string in @var{size-designator},
e.g. @code{(ctype :pid "pid_t")}.
@end deffn
@deffn {Grovel Form} constant (lisp-name &rest c-names) &key type documentation optional
Search for the constant named by the first @var{c-name} string found
to be known to the C preprocessor and define it as @var{lisp-name}.
The @var{type} keyword argument specifies how to grovel the constant:
either @code{integer} (the default) or @code{double-float}. If
@var{optional} is true, no error will be raised if all the
@var{c-names} are unknown. If @var{lisp-name} is a keyword, the actual
constant will be a symbol of the same name interned in the current
package.
@end deffn
@deffn {Grovel Form} feature lisp-feature-name c-name &key feature-list
Adds @var{lisp-feature-name} to the list @var{feature-list} if the @var{c-name}
string is known to the C preprocessor. @var{feature-list} defaults
to @code{cl:*features*}.
@end deffn
@deffn {Grovel Form} define name &optional value
Defines an additional C preprocessor symbol, which is useful for
altering the behavior of included system headers.
@end deffn
@deffn {Grovel Form} cc-flags &rest flags
Adds @var{cc-flags} to the command line arguments used for the C compiler
invocation.
@end deffn
@deffn {Grovel Form} pkg-config-cflags pkg &key optional
Adds @var{pkg} to the command line arguments for the external program
@code{pkg-config} and runs it to retrieve the relevant include flags
used for the C compiler invocation. This syntax can be used instead of
hard-coding paths using @code{cc-flags}, and ensures that include
flags are added correctly on the build system. Assumes
@code{pkg-config} is installed and working. @var{pkg} is a string
that identifies an installed @code{pkg-config} package. See the
pkg-config manual for more information. If @var{optional} is true,
failure to execute @code{pkg-config} does @emph{not} abort
compilation.
@end deffn
@deffn {Grovel Form} cstruct lisp-name c-name slots
Define a @cffi{} foreign struct with the slot data specfied. Slots
are of the form @code{(lisp-name c-name &key type count (signed t))}.
@end deffn
@deffn {Grovel Form} cunion lisp-name c-name slots
Identical to @code{cstruct}, but defines a @cffi{} foreign union.
@end deffn
@deffn {Grovel Form} cstruct-and-class c-name slots
Defines a @cffi{} foreign struct, as with @code{cstruct} and defines a
@acronym{CLOS} class to be used with it. This is useful for mapping
foreign structures to application-layer code that shouldn't need to
worry about memory allocation issues.
@end deffn
@deffn {Grovel Form} cvar namespec type &key read-only
Defines a foreign variable of the specified type, even if that
variable is potentially a C preprocessor pseudo-variable. e.g.
@code{(cvar ("errno" errno) errno-values)}, assuming that errno-values
is an enum or equivalent to type @code{:int}.
The @var{namespec} is similar to the one used in @ref{defcvar}.
@end deffn
@deffn {Grovel Form} cenum name-and-opts &rest elements
Defines a true C enum, with elements specified as @code{((lisp-name
&rest c-names) &key optional documentation)}.
@var{name-and-opts} can be either a symbol as name, or a list
@code{(name &key base-type define-constants)}. If @var{define-constants}
is non-null, a Lisp constant will be defined for each enum member.
@end deffn
@deffn {Grovel Form} constantenum name-and-opts &rest elements
Defines an enumeration of pre-processor constants, with elements
specified as @code{((lisp-name &rest c-names) &key optional
documentation)}.
@var{name-and-opts} can be either a symbol as name, or a list
@code{(name &key base-type define-constants)}. If @var{define-constants}
is non-null, a Lisp constant will be defined for each enum member.
This example defines @code{:af-inet} to represent the value held by
@code{AF_INET} or @code{PF_INET}, whichever the pre-processor finds
first. Similarly for @code{:af-packet}, but no error will be
signalled if the platform supports neither @code{AF_PACKET} nor
@code{PF_PACKET}.
@end deffn
@lisp
(constantenum address-family
((:af-inet "AF_INET" "PF_INET")
:documentation "IPv4 Protocol family")
((:af-local "AF_UNIX" "AF_LOCAL" "PF_UNIX" "PF_LOCAL")
:documentation "File domain sockets")
((:af-inet6 "AF_INET6" "PF_INET6")
:documentation "IPv6 Protocol family")
((:af-packet "AF_PACKET" "PF_PACKET")
:documentation "Raw packet access"
:optional t))
@end lisp
@deffn {Grovel Form} bitfield name-and-opts &rest elements
Defines a bitfield, with elements specified as @code{((lisp-name &rest
c-names) &key optional documentation)}. @var{name-and-opts} can be either a
symbol as name, or a list @code{(name &key base-type)}. For example:
@end deffn
@lisp
(bitfield flags-ctype
((:flag-a "FLAG_A")
:documentation "DOCU_A")
((:flag-b "FLAG_B" "FLAG_B_ALT")
:documentation "DOCU_B")
((:flag-c "FLAG_C")
:documentation "DOCU_C"
:optional t))
@end lisp
@c ===================================================================
@c SECTION: Groveller ASDF Integration
@node Groveller ASDF Integration, Groveller Implementation Notes, Groveller Syntax, The Groveller
@section ASDF Integration
An example software project might contain four files; an
@acronym{ASDF} file, a package definition file, an implementation
file, and a @cffi{}-Grovel specification file.
The @acronym{ASDF} file defines the system and its dependencies.
Notice the use of @code{eval-when} to ensure @cffi{}-Grovel is present
and the use of @code{(cffi-grovel:grovel-file name &key cc-flags)}
instead of @code{(:file name)}.
The @file{example-software.asd} file would look like that:
@lisp
;;; @lispcmt{CFFI-Grovel is needed for processing grovel-file components}
(defsystem "example-software"
:defsystem-depends-on ("cffi-grovel")
:depends-on ("cffi")
:serial t
:components
((:file "package")
(:cffi-grovel-file "example-grovelling")
(:cffi-wrapper-file "example-wrappers")
(:file "example")))
@end lisp
The @file{package.lisp} file would contain one or several
@code{defpackage} forms, to remove circular dependencies and make
building the project easier. Note that you may or may not want to
@code{:use} your internal package.
@impnote{Note that it's a not a good idea to @code{:use} when names may
clash with, say, CL symbols.
Or you could use @code{uiop:define-package} and its @code{:mix} option.}
@lisp
(defpackage #:example-internal
(:use)
(:nicknames #:exampleint))
(defpackage #:example-software
(:export ...)
(:use #:cl #:cffi #:exampleint))
@end lisp
The internal package is created by Lisp code output from the C program
written by @cffi{}-Grovel; if your specification file is
@file{exampleint.lisp}, the @file{exampleint.cffi.lisp} file will contain the
@cffi{} definitions needed by the rest of your project.
@xref{Groveller Syntax}.
@node Groveller Implementation Notes, Wrapper for Inline/Static Functions and Macros, Groveller ASDF Integration, The Groveller
@section Implementation Notes
@cffi{}-Grovel will generate many files that not only architecture-specific,
but also implementation-specific, and should not be distributed.
ASDF will generate these files in its output cache;
if you build with multiple architectures (e.g. with NFS/AFS home
directories) or implementations, it is critical for avoiding clashes
to keep this cache in an implementation-dependent directory (as is the
default).
For @code{foo-internal.lisp}, the resulting @code{foo-internal.c},
@code{foo-internal}, and @code{foo-internal.cffi.lisp} are all
platform-specific, either because of possible reader-macros in
foo-internal.lisp, or because of varying C environments on the host
system. For this reason, it is not helpful to distribute any of those
files; end users building @cffi{}-Grovel based software will need
@code{cffi}-Grovel anyway.
@impnote{For now, after some experimentation with @sc{clisp} having no
long-long, it seems appropriate to assert that the generated @code{.c}
files are architecture and operating-system dependent, but
lisp-implementation independent. This way the same @code{.c} file
(and so the same @code{.grovel-tmp.lisp} file) will be shareable
between the implementations running on a given system.}
@c TODO: document the new wrapper stuff.
@node Wrapper for Inline/Static Functions and Macros, , Groveller Implementation Notes, The Groveller
@section Wrapper for Inline/Static Functions and Macros
In a shared library, information in static/inlined functions and
macros are already removed during the compilation. Wrapper file
enables to write an uninlined function wrapping the call to them.
A wrapper file compilation/loading proceeds as follows:
Unlike groveller which generates C code that emits lisp files
containing cffi definitions, it generates C code, compiles it as a
shared library, loads the library, generate the cffi definitions (as
lisp code) and then loads the lisp code.
It has asdf integration similar to groveller.
@lisp
(defsystem "example-software"
:defsystem-depends-on ("cffi-grovel")
:depends-on ("cffi")
:serial t
:components
((:file "package")
(:cffi-grovel-file "example-grovelling")
(:cffi-wrapper-file "example-wrappers") ;; <<--- this part
(:file "example")))
@end lisp
@deffn {Wrapper Form} defwrapper name-and-options return-type &rest args
@end deffn
@example
static inline int foo(int i) @{
return 1+i;
@};
#define bar(i) (1+(i))
@end example
@lisp
(in-package :mypackage)
(defwrapper ("foo" foo) :int
(i :int))
(defwrapper ("bar" bar) :int
(i :int))
@end lisp
Other forms are similar to grovel files.
@deffn {Wrapper Form} progn &rest forms
Processes a list of forms. Useful for conditionalizing several
forms. For example:
@end deffn
@lisp
#+freebsd
(progn
(constant (ev-enable "EV_ENABLE"))
(constant (ev-disable "EV_DISABLE")))
@end lisp
@deffn {Wrapper Form} include &rest files
Include the specified files (specified as strings) in the generated C
source code.
@end deffn
@deffn {Wrapper Form} in-package symbol
Set the package to be used for the final Lisp output.
@end deffn
@deffn {Wrapper Form} flags &rest flags
Adds @var{cc-flags} to the command line arguments used for the C compiler
invocation.
@end deffn
@deffn {Wrapper Form} proclaim &rest proclaimations
@end deffn
@deffn {Wrapper Form} declaim &rest declaimations
@end deffn
@c ===================================================================
@c CHAPTER: Static Linking
@node Static Linking, Limitations, The Groveller, Top
@chapter Static Linking
On recent enough versions of supported implementations (currently,
GNU CLISP 2.49, CMUCL 2015-11, and SBCL 1.2.17), and with a recent
enough ASDF (3.1.2 or later), you can create a statically linked
Lisp executable image that includes all the C extensions
(wrappers and any other objects output by @code{compile-op})
as well as your Lisp code --- or a standalone application executable.
This makes it easier to deliver your code as a single file.
To dump a statically linked executable image, use:
@lisp
(asdf:load-system :cffi-grovel)
(asdf:operate :static-image-op :example-software)
@end lisp
To dump a statically linked executable standalone application, use:
@lisp
(asdf:load-system :cffi-grovel)
(asdf:operate :static-program-op :example-software)
@end lisp
See @uref{https://common-lisp.net/project/asdf/,,the ASDF
manual} for documentation about @code{image-op} and @code{program-op}
which are the parent operation classes that behave similarly except
they don't statically link C code.
@impnote{There is also an operation @code{:static-runtime-op} to create the
statically linked runtime alone, but it's admittedly not very useful
except as an intermediate step dependency towards building
@code{:static-image-op} or @code{:static-program-op}.}
@c ===================================================================
@c CHAPTER: Limitations
@node Limitations, Platform-specific features, The Groveller, Top
@chapter Limitations
These are @cffi{}'s limitations across all platforms; for information
on the warts on particular Lisp implementations, see
@ref{Implementation Support}.
@itemize @bullet
@item
The tutorial includes a treatment of the primary, intractable
limitation of @cffi{}, or any @acronym{FFI}: that the abstractions
commonly used by C are insufficiently expressive.
@xref{Tutorial-Abstraction,, Breaking the abstraction}, for more
details.
@end itemize
@node Platform-specific features, Glossary, Limitations, Top
@appendix Platform-specific features
Whenever a backend doesn't support one of @cffi{}'s features, a
specific symbol is pushed onto @code{common-lisp:*features*}. The
meanings of these symbols follow.
@table @var
@item cffi-sys::flat-namespace
This Lisp has a flat namespace for foreign symbols meaning that you
won't be able to load two different libraries with homograph functions
and successfully differentiate them through the @code{:library}
option to @code{defcfun}, @code{defcvar}, etc@dots{}
@item cffi-sys::no-foreign-funcall
The macro @code{foreign-funcall} is @strong{not} available. On such
platforms, the only way to call a foreign function is through
@code{defcfun}. @xref{foreign-funcall}, and @ref{defcfun}.
@item cffi-sys::no-long-long
The C @code{long long} type is @strong{not} available as a foreign
type.
However, on such platforms @cffi{} provides its own implementation of
the @code{long long} type for all of operations in chapters
@ref{Foreign Types}, @ref{Pointers} and @ref{Variables}. The
functionality described in @ref{Functions} and @ref{Callbacks} will
not be available.
32-bit Lispworks 5.0+ is an exception. In addition to the @cffi{}
implementation described above, Lispworks itself implements the
@code{long long} type for @ref{Functions}. @ref{Callbacks} are still
missing @code{long long} support, though.
@item cffi-sys::no-stdcall
This Lisp doesn't support the @code{stdcall} calling convention. Note
that it only makes sense to support @code{stdcall} on (32-bit) x86
platforms.
@end table
@node Glossary, Comprehensive Index, Platform-specific features, Top
@appendix Glossary
@table @dfn
@item aggregate type
A @cffi{} type for C data defined as an organization of data of simple
type; in structures and unions, which are themselves aggregate types,
they are represented by value.
@item foreign value
This has two meanings; in any context, only one makes sense.
When using type translators, the foreign value is the lower-level Lisp
value derived from the object passed to @code{translate-to-foreign}
(@pxref{translate-to-foreign}). This value should be a Lisp number or
a pointer (satisfies @code{pointerp}), and it can be treated like any
general Lisp object; it only completes the transformation to a true
foreign value when passed through low-level code in the Lisp
implementation, such as the foreign function caller or indirect memory
addressing combined with a data move.
In other contexts, this refers to a value accessible by C, but which
may only be accessed through @cffi{} functions. The closest you can
get to such a foreign value is through a pointer Lisp object, which
itself counts as a foreign value in only the previous sense.
@item simple type
A @cffi{} type that is ultimately represented as a builtin type;
@cffi{} only provides extra semantics for Lisp that are invisible to C
code or data.
@end table
@node Comprehensive Index, , Glossary, Top
@unnumbered Index
@printindex cp
@bye