Everything described in the section will work verbatim on Win32
when using Cygwin or MinGW, except for one
thing - you will need to replace the run
extension in lisp.run
with the Win32 executable
extension exe
.
For historical reasons, all examples appear to assume UNIX and
use the run
file type (“extension”)
for the CLISP run-time.
This does not mean that they will not work on Win32.
CLISP has a facility for adding external modules (written in C, for example). It is invoked through clisp-link.
A module is a
piece of external code which defines extra Lisp objects, symbols and
functions. A module name must consist of the
characters A
-Z
,
a
-z
, _
,
0
-9
.
The module name “clisp” is reserved.
Normally a module name is derived from the corresponding file name.
clisp-link needs a directory containing:
"modules.d"
"modules.c"
"clisp.h"
clisp-link expects to find these files in a
subdirectory linkkit/
of the current directory.
This can be overridden by the environment variable CLISP_LINKKIT
.
clisp-link operates on CLISP linking sets and on module sets.
A linking set is a directory containing:
makevars
some /bin/sh commands, setting the variables
CC | the C compiler |
CPPFLAGS | flags for the C compiler, when preprocessing or compiling |
CFLAGS | flags for the C compiler, when compiling or linking |
CLFLAGS | flags for the C compiler, when linking |
LIBS | libraries to use when linking |
X_LIBS | additional X Window System libraries to use |
RANLIB | the ranlib command |
FILES | the list of files needed when linking |
modules.h
modules.o
FILES
makevars
lisp.run
lispinit.mem
To run a CLISP contained in some linking set directory
, call
$
directory
/lisp.run-M
directory
/lispinit.mem
or
$
clisp-K
directory
(recommended, since it also passes
-B
to the run-time).
A module set is a directory containing:
NEW_FILES
,
NEW_LIBS
, NEW_MODULES
, TO_LOAD
and optionally TO_PRELOAD
In link.sh the module set directory is referred to
as $modulename/
.
The following variables should be defined in link.sh.
NEW_FILES
NEW_LIBS
lisp.run
belonging to a new linking set.
NEW_MODULES
#P".c"
file in the
module set defines a module of its own. The module name is derived
from the file name.TO_LOAD
lispinit.mem
belonging to a new linking set.
TO_PRELOAD
(optional)the space-separated list of Lisp files to load
into an intermediate lispinit.mem
file, before building the lispinit.mem
belonging to a new linking set.
This variable is usually used to create
(or unlock) the Lisp PACKAGE
s which
must be present when the new #P".c"
files are initialized.
E.g., the FFI:DEF-CALL-IN
functions must reside in already defined packages;
see Example 31.6, “Calling Lisp from C”. You can find a live example in
modules/syscalls/preload.lisp
and modules/syscalls/link.sh.in
.
If you are unlocking a package, you must also
DELETE
it from CUSTOM:*SYSTEM-PACKAGE-LIST*
(see Section 30.2, “Saving an Image”) here
and re-add it to CUSTOM:*SYSTEM-PACKAGE-LIST*
in one of the TO_LOAD
files.
See, e.g., modules/i18n/preload.lisp
and modules/i18n/link.sh.in
.
The command
$
clisp-link create-module-setmodule
file1.c
...
creates a module set in module
directory which refers
(via symbolic links) to file1.c
etc.
The files are expected to be modules of their own.
The command
$
clisp-link add-module-setmodule
source
destination
combines a linking set in directory source
and a
module in directory module
to a new linking set, in the directory
destination
which is newly created.
The command
$
clisp-link runsource
module
...
runs the linking set in directory source
, with the module
in directory module
loaded.
More than one module can be specified.
If CLISP has been built with the configuration option
--with-dynamic-modules
, the loading will be performed
through dynamic loading.
Otherwise - this is much slower - a temporary linking set will be created
and deleted afterwards.
Each module has two initialization functions:
module__name
__init_function_1
(struct module_t* module)called only once when CLISP
discovers while loading a memory image that there is a module present
in the executable (lisp.run
) which was not present at the time the
image was saved. It can be used to create Lisp objects,
e.g. functions or keywords, and is indeed used for that purpose by
modprep.
You do not have to define this function yourself; modprep and “FFI” will do that for you.
If you use “FFI”, (
will add code to this function.FFI:C-LINES
:init-once ...)
The PACKAGE
s must already exist and be unlocked,
cf. TO_PRELOAD
.
If you are using modprep and defining your
own “init-once” function, it must call the
module__
function!name
__init_function_1__modprep
module__name
__init_function_2
(struct module_t* module)called every time CLISP starts.
It can be used to bind names to foreign addresses, since the address
will be different in each invocation of CLISP, and is indeed used
for that purpose by “FFI” (e.g., by FFI:DEF-CALL-OUT
).
It can also be used to set parameters of the libraries to which the
module interfaces, e.g., the pcre module
sets pcre_malloc
and pcre_free
.
You do not have to defined this function yourself; modprep and “FFI” will do that for you.
If you use “FFI”, (
will add code to this function.FFI:C-LINES
:init-always ...)
name
is the module name.
See also Section 30.1, “Customizing CLISP Process Initialization and Termination”.
Each module has a finalization function
module__name
__fini_function
(struct module_t* module)called before exiting CLISP.
You do not have to defined this function yourself; modprep and “FFI” will do that for you.
If you use “FFI”, (
will
add code to this function.FFI:C-LINES
:fini ...)
name
is the module name.
See also Section 30.1, “Customizing CLISP Process Initialization and Termination”.
EXT:MODULE-INFO
Function (
allows one to inquire
about what modules are available in the currently running image.
When called without arguments, it returns the list of module names,
starting with “clisp”. When EXT:MODULE-INFO
&OPTIONAL
name
verbose
)name
is supplied and
names a module, 3 values are returned - name
,
subr-count
,
object-count
.
When verbose
is non-NIL
, the full list of
module lisp function names written in C (Subrs) and
the full list of internal lisp objects available in C code
are additionally returned for the total of 5 values.
When name
is :FFI
, returns the list of
shared libraries opened using :LIBRARY
.
When verbose
is non-NIL
, return the
association list of DLL names and all foreign objects associated with it.
SYS::DYNLOAD-MODULES
--with-dynamic-modules
.Dynamic loading does not work on all operating systems
(dlopen
or equivalent is required).
--with-dynamic-modules
precludes some
efficiency optimizations which are enabled by default.
Function (
loads a shared object file or library containing a number of named
external CLISP modules.
SYS::DYNLOAD-MODULES
filename
({name
}+))
This facility cannot be used to
access arbitrary shared libraries. To do that, use the :LIBRARY
argument to FFI:DEF-CALL-OUT
and FFI:DEF-C-VAR
instead.
External modules for CLISP are shared objects
(dynamic libraries) that contain the
module__
variable, among others.
This serves to register external functions which operate on Lisp-level
structures with CLISP.name
__subr_tab
To use dlopen
with modules,
you should add -fPIC
to the module's compilation options.
Something like cc -shared -o name
.so name
.o
may be needed to produce the shared object file.
To link in the “FFI” bindings for the GNU/Linux operating system, the following steps are needed. (Step 1 and step 2 need not be executed in this order.)
Create a new module set
$
clisp-link create-module-set linux /somewhere
/bindings/linux.c
Modify the newly created
linux/link.sh
add -lm
to the libraries
replace
NEW_LIBS="$file_list"
with
NEW_LIBS="$file_list -lm"
load linux.fas
before saving the
memory image
replace
TO_LOAD=''
with
TO_LOAD='/somewhere
/bindings/linux.fas'
Compile linux.lisp
, creating
linux.c
$
clisp -c /somewhere
/bindings/linux.lisp
Create a new linking set
$
clisp-link add-module-set linux base base+linux
Run and try it
$
base+linux/lisp.run -M base+linux/lispinit.mem -x '(linux:stat "/tmp")'
There are some tools to facilitate easy module writing.
If your module is written in C, you can pre-process your
sources with modprep in the CLISP distribution and define lisp
functions with the DEFUN
macro:
DEFUN(MY-PACKAGE:MY-FUNCTION-NAME, arg1 arg2 &KEY
FOO BAR) {
if (!boundp(STACK_0)) STACK_0 = fixnum(0); /* BAR */
if (!boundp(STACK_1)) STACK_1 = fixnum(1); /* FOO */
pushSTACK(`MY-PACKAGE::SOME-SYMBOL`); /* create a symbol in the package */
pushSTACK(`#(:THIS :IS :A :VECTOR)`); /* some vector, created once */
pushSTACK(``MY-PACKAGE::MY-FUNCTION-NAME``); /* double `` means FUNCTION */
VALUES1(listof(7)); /* cons up a new list and clean up the STACK */
}
Then (MY-PACKAGE:MY-FUNCTION-NAME 'A 12 :FOO T)
will
return (A 12 T 0 MY-PACKAGE::SOME-SYMBOL #(:THIS
:IS :A :VECTOR) #<ADD-ON-SYSTEM-FUNCTION
MY-PACKAGE:MY-FUNCTION-NAME>)
(assuming you EXPORT
ed MY-FUNCTION-NAME
from
“MY-PACKAGE”).
Another useful macros are:
DEFVAR
DEFFLAGSET
STACK
and return the combined flag
valueDEFCHECKER
See modules/syscalls/
and
other included modules for more examples and file modprep for full
documentation.
If you manipulate Lisp objects, you need to watch out for GC-safety.
If your module is written in C, you will probably want
to #include "clisp.h"
to access CLISP objects.
You will certainly need to read "clisp.h"
and the code in
included modules, but here are
some important hints that you will need to keep in mind:
allocate_*()
functions) - but not C
allocations (malloc
et al) -
and must be saved on the STACK
using cpp macros
pushSTACK()
, popSTACK()
and skipSTACK()
.TheFoo()
macro, e.g.,
TheCons(my_cons)->Car
, but first check the
type with consp()
.STACK
, as illustrated
in the above example.begin_system_call()
/end_system_call()
pairs. These macros, defined in "clisp.h"
, save and restore
registers used by CLISP which could be clobbered by a system call.
If your module uses “FFI” to interface to a C library,
you might want to make your module package
case-sensitive and use
exporting.lisp
in the CLISP distribution to make “FFI” forms
and DEFUN
, DEFMACRO
at al export the symbols they define.
See modules/netica/
,
modules/matlab/
and
modules/bindings/
for examples.
When deciding how to write a module: whether to use “FFI” or to stick with C and modprep, one has to take into account several issues:
“FFI” has a noticeable overhead:
compare RAWSOCK:HTONS
(defined
in modules/rawsock/rawsock.c
)
with
(FFI:DEF-CALL-OUT
htons (:name "htons") (:library :default)
(:arguments (s ffi:short)) (:return-type ffi:short) (:language :stdc))
and observe that RAWSOCK:HTONS
is
almost 3 times as fast (this really does compare the “FFI”
overhead to the normal lisp function call because
htons
is computationally trivial).
This difference will matter only if you call a simple function very
many times, in which case it would make sense to put the loop itself
into C.
First of all, “FFI” is not as widely ported as CLISP, so it is possible that you will face a platform where CLISP runs but “FFI” is not present.
Second, it is much easier to handle portability in C:
observe the alternative implementations
of htonl
et al in
modules/rawsock/rawsock.c
.
Third, certain C structures have different layout on different platforms, and functions may take 64-bit arguments on some platforms and 32-bit arguments on others; so the “FFI” code has to track those differences.
:LIBRARY
argument to FFI:DEF-CALL-OUT
and
FFI:DEF-C-VAR
, you do not need to leave your CLISP session to try
out your code. This is a huge advantage for rapid prototyping.
&OPTIONAL
and
&KEY
word arguments etc), you will need to write wrappers to your
FFI:FOREIGN-FUNCTION
s, while in C you can do that directly.
The same goes for “polymorphism”: accepting different
argument types (like, e.g., POSIX:RESOLVE-HOST-IPADDR
does) would require a lisp
wrapper for FFI:FOREIGN-FUNCTION
s.
If you are comfortable with C, you might find the CLISP C module facilities (e.g., modprep) very easy to use.
CLISP “FFI”, on the other hand, is quite high-level, so, if you are more comfortable with high-level languages, you might find it easier to write “FFI” forms than C code.
FFI:DEF-CALL-OUT
form does not describe the function's expectations
with respect to the arguments and return values (including
ALLOCATION
), you will probably learn that the hard way.
If the module is written in C, all the opportunities to shoot
oneself in the foot (and other body parts) are wide open
(although well known to most C users).
However, with C, one has to watch
for GC-safety too.
The following modules come with the source distribution of CLISP (but are not necessarily built in a particular binary distribution):
Call the operating system functions from CLISP. The following platforms are supported:
Call Xlib functions from CLISP. Two implementations are supplied:
faster, with additional features, but not quite complete yet. Please try it first and use mit-clx only if new-clx does not work for you. new-clx comes with several demos, please try them: run
$
clisp-K
full-i
modules/clx/new-clx/demos/clx-demos.lisp
and follow the intructions.
n
-queens
problem on a n
×n
checkboard (a toy
example for the users to explore the CLISP module system,
see modules/queens/
).
VECTOR
s using
ZLIB.
To use modules, read unix/INSTALL
and build CLISP in directory build-dir
with,
e.g.,
$
./configure --with-module=pcre --with-module=clx/new-clx --build build-dir
then run it with
$
./build-dir/clisp-K
full
This will create a base linking set with modules i18n, regexp and syscalls; and a full linking set with modules pcre and new/clx in addition to the 3 base modules.
See Chapter 32, Extensions Implemented as Modules for individual module documentation.
These notes document CLISP version 2.41 | Last modified: 2006-10-13 |