An example project is included in the ECL source distribution in the
examples/embed/
directory.
This example consists of a Common Lisp library (hello-lisp.lisp
) and a
system definition (hello-lisp.asd
, See Compiling with ASDF) that is
called from a C program (hello.c
). The example Makefile
shows how
to build a static library from the Lisp library and link it with the C program.
int
cl_boot (int argc, char **argv);
¶Setup the lisp environment.
An integer with the number of arguments to this program.
A vector of strings with the arguments to this program.
Description
This function must be called before any other function from the ECL library, including the creation of any lisp object or evaluating any lisp code. The only exception are ecl_set_option
and ecl_get_option
.
int
cl_shutdown (void);
¶Close the lisp environment.
Description
This function must be called before exiting a program that uses the ECL environment. It performs some cleaning, including the execution of any finalizers, unloading shared libraries and deleting temporary files that were created by the compiler.
void
ecl_set_option (int option, cl_fixnum value);
¶Set a boot option.
An integer from Table 1.1.
A cl_index
value for this option
Description
This functions sets the value of different options that have to be customized before ECL boots. The table of options and default values [Table 1.1] shows that some of them are boolean, and some of them are unsigned integers.
We distinguish three sets of values. The first set determines whether ECL handles certain exceptions, such as access to forbidden regions of memory, interrupts via , floating point exceptions, etc.
The second set is related to the sizes of different stacks. Currently ECL uses four stacks: a bind stack for keeping assignments to special variables; a frame stack for implementing blocks, tagbodys and catch points; an interpreter stack for evaluating bytecodes, and finally the machine or C stack, of the computer we run in. We can set the expected size of these stacks, together with the size of a safety area which, if penetrated, will lead to the generation of a correctable error.
Name (ECL_OPT_*) | Type | Default | Description |
---|---|---|---|
INCREMENTAL_GC | boolean | TRUE | Activate generational garbage collector. |
TRAP_SIGSEGV | boolean | TRUE | Capture SIGSEGV signals. |
TRAP_SIGFPE | boolean | TRUE | Capture floating point exceptions. |
TRAP_SIGINT | boolean | TRUE | Capture user interrupts. |
TRAP_SIGILL | boolean | TRUE | Capture SIGILL exception. |
TRAP_INTERRUPT_SIGNAL | boolean | TRUE | Capture the signal that implements mp:interrupt-process . |
SIGNAL_HANDLING_THREAD | boolean | TRUE | Create a signal to capture and process asynchronous threads (See Asynchronous signals). |
BOOTED | boolean | TRUE/FALSE | Has ECL booted (read only). |
BIND_STACK_SIZE | cl_index | 8192 | Size of stack for binding special variables. |
BIND_STACK_SAFETY_AREA | cl_index | 128 | |
FRAME_STACK_SIZE | cl_index | 2048 | Size of stack for nonlocal jumps. |
FRAME_STACK_SAFETY_AREA | cl_index | 128 | |
LISP_STACK_SIZE | cl_index | 32768 | Size of interpreter stack. |
LISP_STACK_SAFETY_AREA | cl_index | 128 | |
C_STACK_SIZE | cl_index | 0 or 1048576 | Size of C stack in bytes. The effect and default value of this option depends on the operating system. On Unix, the default is 0 which means that ECL will use the stack size provided by the OS. If set to a non-default value, ECL will set the stack size to the given value unless the stack size provided by the OS is already large enough. On Windows, the stack size is set at build time and cannot be changed at runtime. Here, we use a default of 1 MiB. For other operating systems, it is up to the user to set this value to the available stack size so that ECL can reliably detect stack overflows. |
C_STACK_SAFETY_AREA | cl_index | 4192 | |
THREAD_INTERRUPT_SIGNAL | unsigned int | 0 | If nonzero, specify the unix signal which is used to communicate between different Lisp threads. |
cl_fixnum
ecl_get_option (int option);
¶Read the value of a boot option.
An integer from Table 1.1.
Description
This functions reads the value of different options that have to be customized before ECL boots. The table of options and default values is Table 1.1.
bool
ecl_import_current_thread (cl_object name, cl_object bindings);
¶Import an external thread in the Lisp environment.
Thread name.
Unused (specifying initial bindings for external threads is not supported currently)
True if the thread was successfully imported, false otherwise.
Description
External threads, i.e. threads which are not created in the Lisp world using the routines described in Processes (native threads), need to be imported with ecl_import_current_thread
before Lisp code can be executed.
See also
void
ecl_release_current_thread (void);
¶Release an external thread imported with ecl_import_current_thread
. Must be called before thread exit to prevent memory leaks.
Specify a non-standard installation directory.
Description
ECL includes various files for external modules (e.g. asdf, sockets), character encodings or documentation strings. The installation directory for these files is chosen during build time by the configure script. If the directory is moved to a different place, the ECLDIR
environment variable should be updated accordingly. Note that the contents of the variable are parsed as a Common Lisp pathname, thus it must end with a slash.
Create a protected region.
C Macro
cl_env_ptr env = ecl_process_env(); ECL_CATCH_ALL_BEGIN(env) { /* * Code that is protected. Uncaught lisp conditions, THROW, * signals such as SIGSEGV and SIGBUS may cause jump to * this region. */ } ECL_CATCH_ALL_IF_CAUGHT { /* * If the exception, lisp condition or other control transfer * is caught, this code is executed. */ } ECL_CATCH_ALL_END /* * In all cases we exit here. */
Description
This is a set of three macros that create an unwind-protect
region that prevents any nonlocal transfer of control to outer loops. In the Lisp speak, the previous code is equivalent to
(block nil (unwind-protect (progn ;; Code that is protected ) (return nil)))
As explained in ECL_UNWIND_PROTECT
, it is normally advisable to set up an unwind-protect frame to avoid the embedded lisp code to perform arbitrary transfers of control.
See also
Create a protected region.
C Macro
cl_env_ptr env = ecl_process_env(); ECL_UNWIND_PROTECT_BEGIN(env) { /* * Code that is protected. Uncaught lisp conditions, THROW, * signals such as SIGSEGV and SIGBUS may cause jump to * this region. */ } ECL_UNWIND_PROTECT_EXIT { /* * If the exception, lisp condition or other control transfer * is caught, this code is executed. After this code, the * process will jump to the original destination of the * THROW, GOTO or other control statement that was interrupted. */ } ECL_UNWIND_PROTECT_END /* * We only exit here if NO nonlocal jump was interrupted. */
Description
When embedding ECL it is normally advisable to set up an unwind-protect
frame to avoid the embedded lisp code to perform arbitrary transfers of control. Furthermore, the unwind protect form will be used in at least in the following occasions:
ext:quit
, ECL unwinds up to the outermost frame, which may be an ECL_CATCH_ALL
or ECL_UNWIND_PROTECT
macro.
Besides this, normal mechanisms for exit, such as ext:quit
, and uncaught exceptions, such as serious signals (See Synchronous signals), are best handled using unwind-protect
blocks.
See also
Clear all pending signals and exceptions.
Description
This macro clears all pending interrupts.
See also
Postpone handling of signals and exceptions.
Description
This macro sets a thread-local flag indicating that all received signals should be queued for later processing. Note that it is not possible to execute lisp code while interrupts are disabled in this way. For this purpose, use the mp:without-interrupts
macro. Every call to ecl_disable_interrupts
must be followed by a corresponding call to ecl_enable_interrupts
, otherwise race conditions will appear.
See also
Activate handling of signals and exceptions.
Description
This macro sets a thread-local flag indicating that all received signals can be handled. If there are any pending signals, they will be immediately processed.
See also
Execute Lisp code with correct floating point environment
Description
Unless floating point exceptions are disabled (via the
--without-fpe
configure option or ECL_OPT_TRAP_SIGFPE
runtime option), ECL will change the floating point environment when
booting. This macro allows for execution of Lisp code while saving and
later restoring the floating point environment of surrounding C code
so that changes in the floating point environment don’t leak outside.
ECL_WITH_LISP_FPE
can be also used before ECL has booted.
Example
#include <ecl/ecl.h> #include <stdio.h> int main(int argc, char **argv) { ECL_WITH_LISP_FPE_BEGIN { cl_boot(argc, argv); } ECL_WITH_LISP_FPE_END; double a = 1.0 / 0.0; double b; ECL_WITH_LISP_FPE_BEGIN { cl_object form = ecl_read_from_cstring("(handler-case" "(/ 1d0 0d0)" "(division-by-zero () 0d0))"); b = ecl_to_double(si_safe_eval(3, form, ECL_NIL, ECL_NIL)); } ECL_WITH_LISP_FPE_END; printf("%g %g\n", a, b); cl_shutdown(); return 0; }
will output
inf 0
See also