mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-23 21:10:29 +02:00
Removed old "dynamic linking and modules" text.
This commit is contained in:
parent
64744a7ff8
commit
4d6444b86a
1 changed files with 4 additions and 207 deletions
|
@ -484,8 +484,7 @@ integrates dynamically linked libraries into the module system.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Low level dynamic linking::
|
* Low level dynamic linking::
|
||||||
* Compiled Code Modules::
|
* Extensions::
|
||||||
* Dynamic Linking and Compiled Code Modules::
|
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Low level dynamic linking
|
@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
|
@code{dynamic-args-call} considerably. There is glue code available in
|
||||||
the Guile contrib archive to make @file{libffi} accessible from Guile.
|
the Guile contrib archive to make @file{libffi} accessible from Guile.
|
||||||
|
|
||||||
@node Compiled Code Modules
|
@node Extensions
|
||||||
@subsection Putting Compiled Code into Modules
|
@subsection Writing Dynamically Loadable Extensions
|
||||||
|
|
||||||
@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).
|
|
||||||
|
|
||||||
|
XXX - document @code{load-extension}, @code{scm_register_extension}
|
||||||
|
|
||||||
@c Local Variables:
|
@c Local Variables:
|
||||||
@c TeX-master: "guile.texi"
|
@c TeX-master: "guile.texi"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue