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
|
||||
* 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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue