(guile.info.gz) Extensions
Info Catalog
(guile.info.gz) Low level dynamic linking
(guile.info.gz) Dynamic Libraries
31.4.2 Writing Dynamically Loadable Extensions
----------------------------------------------
Higher level linking routines allow you to manage loadable modules when
multiple scheme modules require the same dynamically linked library. As
we described in section A Sample Guile Extension, we write a C
module which contains an init function, and then use the
`load-extension' to link the library and run the init function.
However, let's assume that we had two scheme modules (for example, (math
general) and (science electrons)) which both required the
`libguile-bessel' routines. We would not want to link the shared file
twice because it wastes memory, and even if we were not concerned with
that, it would create symbol conflicts. We cannot designate one to do
the loading, since we may only want one or the other (or both) at any
given time. These routines solve this problem.
-- Scheme Procedure: load-extension lib init
-- C Function: scm_load_extension (SCM lib, SCM init)
-- C Function: scm_c_load_extension (const char *lib, const char *init)
Most of the time, when this function is called, it is equivalent to
calling `(dynamic-call init (dynamic-link lib))'. It simply uses the
low-level dynamic linking routines to link the shared file, and call
its init function. However, if the library and init function has been
pre-registered, it skips the linking of the shared file, and calls the
replacement init function which was designated by the registration.
That way both of our modules can contain the line
(load-extension "libguile-bessel" "init_bessel")
If, for example, (math general) gets loaded first, then it will do
the standard thing and links the shared file, and calls init_bessel.
When (science electrons) gets loaded, the load-extension line does not
cause the shared file to be linked. Instead it simply causes the
replacement init function to be run.
-- C Function: scm_c_register_extension (const char *lib, const char
*init, void (*func) (void *), void *data)
We utilize `scm_c_register_extension' from the init function of our
module to register our replacement function. The bessel function
example would then look like
#include <math.h>
#include <libguile.h>
static double pi; /* Random Global Variable */
SCM
j0_wrapper (SCM x)
{
return scm_make_real (j0 (scm_num2dbl (x, "j0")));
}
void
define_functions (void *data)
{
scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper);
}
void
init_bessel ()
{
pi = 3.14159265; /* Initialize our global var */
define_functions (NULL);
scm_c_register_extension ("libguile-bessel", "init_bessel",
define_functions, NULL);
}
This way the first time `load-extension' is called, the shared
library is linked, the global variable is initialized, the proper scheme
functions (`j0') are defined, and the replacement init function is
registered. The second time `load-extension' is called, it finds the
replacement function and calls `define_functions', without redundantly
attempting to link the shared file, or reinitializing our global
variables.
The fourth argument to `scm_c_register_extension' is a pointer which
gets passed to the replacement init function which you can use for
anything your init function might need.
The first (`lib') argument is allowed to be NULL. In which case only
the `init' argument is used when searching through the registered
extensions. This is useful when you don't know the library name (which
isn't really relevant anyway in a completely linked program) and you
are sure that INIT is unique (which it must be for static linking).
Info Catalog
(guile.info.gz) Low level dynamic linking
(guile.info.gz) Dynamic Libraries
automatically generated byinfo2html