GNU Info

Info Node: (guile.info)Dynamic Linking and Compiled Code Modules

(guile.info)Dynamic Linking and Compiled Code Modules


Prev: Compiled Code Modules Up: Dynamic Linking from Marius
Enter node , (file) or (file)node

Dynamic Linking and Compiled Code Modules
-----------------------------------------

The most interesting application of dynamically linked libraries is
probably to use them for providing _compiled code modules_ to Scheme
programs.  As much fun as programming in Scheme is, every now and then
comes the need to write some low-level C stuff to make Scheme even more
fun.

Not only can you put these new primitives into their own module (see the
previous section), you can even put them into a shared library that is
only then linked to your running Guile image when it is actually needed.

An example will hopefully make everything clear.  Suppose we want to
make the Bessel functions of the C library available to Scheme in the
module `(math bessel)'.  First we need to write the appropriate glue
code to convert the arguments and return values of the functions from
Scheme to C and back.  Additionally, we need a function that will add
them to the set of Guile primitives.  Because this is just an example,
we will only implement this for the `j0' function, tho.

     #include <math.h>
     #include <guile/gh.h>
     
     SCM
     j0_wrapper (SCM x)
     {
       return gh_double2scm (j0 (gh_scm2double (x)));
     }
     
     void
     init_math_bessel ()
     {
       gh_new_procedure1_0 ("j0", j0_wrapper);
     }

We can already try to bring this into action by manually calling the low
level functions for performing dynamic linking.  The C source file needs
to be compiled into a shared library.  Here is how to do it on
GNU/Linux, please refer to the `libtool' documentation for how to
create dynamically linkable libraries portably.

     gcc -shared -o libbessel.so -fPIC bessel.c

Now fire up Guile:

     (define bessel-lib (dynamic-link "./libbessel.so"))
     (dynamic-call "init_math_bessel" bessel-lib)
     (j0 2)
     => 0.223890779141236

The filename `./libbessel.so' should be pointing to the shared library
produced with the `gcc' command above, of course.  The second line of
the Guile interaction will call the `init_math_bessel' function which
in turn will register the C function `j0_wrapper' with the Guile
interpreter under the name `j0'.  This function becomes immediately
available and we can call it from Scheme.

Fun, isn't it?  But we are only half way there.  This is what `apropos'
has to say about `j0':

     (apropos 'j0)
     -| the-root-module: j0     #<primitive-procedure j0>

As you can see, `j0' is contained in the root module, where all the
other Guile primitives like `display', etc live.  In general, a
primitive is put into whatever module is the "current module" at the
time `gh_new_procedure' is called.  To put `j0' into its own module
named `(math bessel)', we need to make a call to
`scm_register_module_xxx'.  Additionally, to have Guile perform the
dynamic linking automatically, we need to put `libbessel.so' into a
place where Guile can find it.  The call to `scm_register_module_xxx'
should be contained in a specially named "module init function".  Guile
knows about this special name and will call that function automatically
after having linked in the shared library.  For our example, we add the
following code to `bessel.c':

     void scm_init_math_bessel_module ()
     {
       scm_register_module_xxx ("math bessel", init_math_bessel);
     }

The general pattern for the name of a module init function is:
`scm_init_', followed by the name of the module where the individual
hierarchical components are concatenated with underscores, followed by
`_module'.  It should call `scm_register_module_xxx' with the correct
module name and the appropriate initialization function.  When that
initialization function will be called, a newly created module with the
right name will be the _current module_ so that all definitions that
the initialization functions makes will end up in the correct module.

After `libbessel.so' has been rebuild, we need to place the shared
library into the right place.  When Guile tries to autoload the `(math
bessel)' module, it looks not only for a file called `math/bessel.scm'
in its `%load-path', but also for `math/libbessel.so'.  So all we need
to do is to create a directory called `math' somewhere in Guile's
`%load-path' and place `libbessel.so' there.  Normally, the current
directory `.' is in the `%load-path', so we just use that for this
example.

     % mkdir maths
     % cd maths
     % ln -s ../libbessel.so .
     % cd ..
     % guile
     guile> (use-modules (math bessel))
     guile> (j0 2)
     0.223890779141236
     guile> (apropos 'j0)
     -| bessel: j0      #<primitive-procedure j0>

That's it!

Note that we used a symlink to make `libbessel.so' appear in the right
spot.  This is probably not a bad idea in general.  The directories
that the `%load-path' normally contains are supposed to contain only
architecture independent files.  They are not really the right place
for a shared library.  You might want to install the libraries
somewhere below `exec_prefix' and then symlink to them from the
architecture independent directory.  This will at least work on
heterogenous systems where the architecture dependent stuff resides in
the same place on all machines (which seems like a good idea to me
anyway).


automatically generated by info2www version 1.2.2.9