Copyright (C) 2000-2012 |
GNU Info (guile.info)Dynamic Linking and Compiled Code ModulesDynamic 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 |