When writing C code for use with Guile, you typically define a set of
C functions, and then make some of them visible to the Scheme world by
calling scm_c_define_gsubr
or related functions. If you have
many functions to publish, it can sometimes be annoying to keep the
list of calls to scm_c_define_gsubr
in sync with the list of
function definitions.
Guile provides the guile-snarf
program to manage this problem.
Using this tool, you can keep all the information needed to define the
function alongside the function definition itself; guile-snarf
will extract this information from your source code, and automatically
generate a file of calls to scm_c_define_gsubr
which you can
#include
into an initialization function.
The snarfing mechanism works for many kind of initialization actions,
not just for collecting calls to scm_c_define_gsubr
. For a
full list of what can be done, See Snarfing Macros.
The guile-snarf
program is invoked like this:
guile-snarf [-o outfile] [cpp-args ...]
This command will extract initialization actions to outfile.
When no outfile has been specified or when outfile is
-
, standard output will be used. The C preprocessor is called
with cpp-args (which usually include an input file) and the
output is filtered to extract the initialization actions.
If there are errors during processing, outfile is deleted and the program exits with non-zero status.
During snarfing, the pre-processor macro SCM_MAGIC_SNARFER
is
defined. You could use this to avoid including snarfer output files
that don’t yet exist by writing code like this:
#ifndef SCM_MAGIC_SNARFER #include "foo.x" #endif
Here is how you might define the Scheme function clear-image
,
implemented by the C function clear_image
:
#include <libguile.h>
SCM_DEFINE (clear_image, "clear-image", 1, 0, 0,
(SCM image),
"Clear the image.")
{
/* C code to clear the image in image
... */
}
void
init_image_type ()
{
#include "image-type.x"
}
The SCM_DEFINE
declaration says that the C function
clear_image
implements a Scheme function called
clear-image
, which takes one required argument (of type
SCM
and named image
), no optional arguments, and no rest
argument. The string "Clear the image."
provides a short help
text for the function, it is called a docstring.
SCM_DEFINE
macro also defines a static array of characters
initialized to the Scheme name of the function. In this case,
s_clear_image
is set to the C string, "clear-image". You might
want to use this symbol when generating error messages.
Assuming the text above lives in a file named image-type.c, you will need to execute the following command to prepare this file for compilation:
guile-snarf -o image-type.x image-type.c
This scans image-type.c for SCM_DEFINE
declarations, and writes to image-type.x the output:
scm_c_define_gsubr ("clear-image", 1, 0, 0, (SCM (*)() ) clear_image);
When compiled normally, SCM_DEFINE
is a macro which expands to
the function header for clear_image
.
Note that the output file name matches the #include
from the
input file. Also, you still need to provide all the same information
you would if you were using scm_c_define_gsubr
yourself, but you
can place the information near the function definition itself, so it is
less likely to become incorrect or out-of-date.
If you have many files that guile-snarf
must process, you should
consider using a fragment like the following in your Makefile:
snarfcppopts = $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) .SUFFIXES: .x .c.x: guile-snarf -o $@ $< $(snarfcppopts)
This tells make to run guile-snarf
to produce each needed
.x file from the corresponding .c file.
The program guile-snarf
passes its command-line arguments
directly to the C preprocessor, which it uses to extract the
information it needs from the source code. this means you can pass
normal compilation flags to guile-snarf
to define preprocessor
symbols, add header file directories, and so on.