1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-23 13:00:34 +02:00

Removed old "dynamic linking and modules" text.

This commit is contained in:
Marius Vollmer 2001-11-13 15:19:29 +00:00
parent 64744a7ff8
commit 4d6444b86a

View file

@ -484,8 +484,7 @@ integrates dynamically linked libraries into the module system.
@menu
* Low level dynamic linking::
* Compiled Code Modules::
* Dynamic Linking and Compiled Code Modules::
* Extensions::
@end menu
@node Low level dynamic linking
@ -614,212 +613,10 @@ can extend the Spartan functionality of @code{dynamic-call} and
@code{dynamic-args-call} considerably. There is glue code available in
the Guile contrib archive to make @file{libffi} accessible from Guile.
@node Compiled Code Modules
@subsection Putting Compiled Code into Modules
@c FIXME::martin: Change all gh_ references to their scm_ equivalents.
The new primitives that you add to Guile with @code{gh_new_procedure}
or with any of the other mechanisms are normally placed into the same
module as all the other builtin procedures (like @code{display}).
However, it is also possible to put new primitives into their own
module.
The mechanism for doing so is not very well thought out and is likely to
change when the module system of Guile itself is revised, but it is
simple and useful enough to document it as it stands.
What @code{gh_new_procedure} and the functions used by the snarfer
really do is to add the new primitives to whatever module is the
@emph{current module} when they are called. This is analogous to the
way Scheme code is put into modules: the @code{define-module} expression
at the top of a Scheme source file creates a new module and makes it the
current module while the rest of the file is evaluated. The
@code{define} expressions in that file then add their new definitions to
this current module.
Therefore, all we need to do is to make sure that the right module is
current when calling @code{gh_new_procedure} for our new primitives.
Unfortunately, there is not yet an easy way to access the module system
from C, so we are better off with a more indirect approach. Instead of
adding our primitives at initialization time we merely register with
Guile that we are ready to provide the contents of a certain module,
should it ever be needed.
@deftypefun void scm_register_module_xxx (char *@var{name}, void (*@var{initfunc})(void))
Register with Guile that @var{initfunc} will provide the contents of the
module @var{name}.
The function @var{initfunc} should perform the usual initialization
actions for your new primitives, like calling @code{gh_new_procedure} or
including the file produced by the snarfer. When @var{initfunc} is
called, the current module is a newly created module with a name as
indicated by @var{name}. Each definition that is added to it will be
automatically exported.
The string @var{name} indicates the hierachical name of the new module.
It should consist of the individual components of the module name
separated by single spaces. That is, the Scheme module name @code{(foo
bar)}, which is a list, should be written as @code{"foo bar"} for the
@var{name} parameter.
You can call @code{scm_register_module_xxx} at any time, even before
Guile has been initialized. This might be useful when you want to put
the call to it in some initialization code that is magically called
before main, like constructors for global C++ objects.
An example for @code{scm_register_module_xxx} appears in the next section.
@end deftypefun
Now, instead of calling the initialization function at program startup,
you should simply call @code{scm_register_module_xxx} and pass it the
initialization function. When the named module is later requested by
Scheme code with @code{use-modules} for example, Guile will notice that
it knows how to create this module and will call the initialization
function at the right time in the right context.
@node Dynamic Linking and Compiled Code Modules
@subsection Dynamic Linking and Compiled Code Modules
The most interesting application of dynamically linked libraries is
probably to use them for providing @emph{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 @samp{(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 @code{j0} function.
@c FIXME::martin: Change all gh_ references to their scm_ equivalents.
@smallexample
#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);
@}
@end smallexample
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 @code{libtool} documentation for how to
create dynamically linkable libraries portably.
@smallexample
gcc -shared -o libbessel.so -fPIC bessel.c
@end smallexample
Now fire up Guile:
@smalllisp
(define bessel-lib (dynamic-link "./libbessel.so"))
(dynamic-call "init_math_bessel" bessel-lib)
(j0 2)
@result{} 0.223890779141236
@end smalllisp
The filename @file{./libbessel.so} should be pointing to the shared
library produced with the @code{gcc} command above, of course. The
second line of the Guile interaction will call the
@code{init_math_bessel} function which in turn will register the C
function @code{j0_wrapper} with the Guile interpreter under the name
@code{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
@code{apropos} has to say about @code{j0}:
@smallexample
(apropos 'j0)
@print{} the-root-module: j0 #<primitive-procedure j0>
@end smallexample
As you can see, @code{j0} is contained in the root module, where all
the other Guile primitives like @code{display}, etc live. In general,
a primitive is put into whatever module is the @dfn{current module} at
the time @code{gh_new_procedure} is called. To put @code{j0} into its
own module named @samp{(math bessel)}, we need to make a call to
@code{scm_register_module_xxx}. Additionally, to have Guile perform
the dynamic linking automatically, we need to put @file{libbessel.so}
into a place where Guile can find it. The call to
@code{scm_register_module_xxx} should be contained in a specially
named @dfn{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
@file{bessel.c}:
@smallexample
void scm_init_math_bessel_module ()
@{
scm_register_module_xxx ("math bessel", init_math_bessel);
@}
@end smallexample
The general pattern for the name of a module init function is:
@samp{scm_init_}, followed by the name of the module where the
individual hierarchical components are concatenated with underscores,
followed by @samp{_module}. It should call
@code{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
@emph{current module} so that all definitions that the initialization
functions makes will end up in the correct module.
After @file{libbessel.so} has been rebuild, we need to place the shared
library into the right place. When Guile tries to autoload the
@samp{(math bessel)} module, it looks not only for a file called
@file{math/bessel.scm} in its @code{%load-path}, but also for
@file{math/libbessel.so}. So all we need to do is to create a directory
called @file{math} somewhere in Guile's @code{%load-path} and place
@file{libbessel.so} there. Normally, the current directory @file{.} is
in the @code{%load-path}, so we just use that for this example.
@smallexample
% mkdir maths
% cd maths
% ln -s ../libbessel.so .
% cd ..
% guile
guile> (use-modules (math bessel))
guile> (j0 2)
0.223890779141236
guile> (apropos 'j0)
@print{} bessel: j0 #<primitive-procedure j0>
@end smallexample
That's it!
Note that we used a symlink to make @file{libbessel.so} appear in the
right spot. This is probably not a bad idea in general. The
directories that the @file{%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 @samp{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).
@node Extensions
@subsection Writing Dynamically Loadable Extensions
XXX - document @code{load-extension}, @code{scm_register_extension}
@c Local Variables:
@c TeX-master: "guile.texi"