This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Getting the head around dynamic linking



There was some discussion on this list about the Right Way(TM) to have
dynamic linking interact with the module system.  I'll just summarize
how it was decided it should work.  Sorry about the long message. 

; > Err, not quite. Modules are .scm files - they're just a way to
; > restrict namespaces in Scheme.
; 
; Right, I dig this now. Dunno how to write one but I do know
; where they live and what they do.

Well, this is not exactly true.  A module is just a namespace.  It can
be defined in multiple pieces, in any or no .scm file, or in a .so
file.  I point this out because it means that if you're debugging a
module, at the guile prompt you can just do:

guile> (define-module (lib buggy))
guile> (define-public buggy-function fixed-code)

and change the bindings in any module.  But guile is clever about
modules; if you ask it for one that hasn't been defined, it will
search %load-path.  Currently I don't think there's a way to force
re-autoloading if the file changes (maintainers? anyone eager to put
one in?)

; > You can load/initialize .so files with
; > (dynamic-call 'function (dynamic-link "foo.so")).
; 
; Yup, got this working too.

This works, but isn't the nicest way.  There was some debate on this;
some modules may not want to export any functions directly, in which
case you might want the scheme wrappers to do this.  Alas, you can't
do much about passing arguments to the dynamic functions. 

; At the moment I'm using the technique as follows:
; 
; -- in the C code (index.c) --
; 
; void initialise_for_scheme( void )
<good initialization code>
; 
; -- in the Makefile --
; 
; index.so : index.c
; 	gcc -shared -O2 $< -o $@
; 	strip $@

Ideally, this would be done using automake and libtool.  Alas, libtool
doesn't interact so well with dynamic loading; you end up having to do
"ln -s .libs/libfoo.so ." or something.


; And then I have access to my data type and primitives. Note that
; this uses the normal guile which was compiled with no knowledge of
; my extensions nor with any -lblahblah options other than the usual.
; It doesn't use libtool or anything wierd.

libtool is just a gizmo to produce shared libraries in a portable
way.  It's probably worth using, if only because it'll save you having
to worry about -fPIC and suchlike.  Automake will use it
automatically, and just generally make you happy --- if you're writing
a large portable package. 

; If you want to do tidy it up a bit more, you would have to
; install index.so into /usr/local/lib/guile_index.so.1.0,
; softlink /usr/local/lib/guile_index.so.1 and write some suitable
; scheme code to go into /usr/local/share/guile/site/inxex.scm
; one line of which would be:
; 
; (dynamic-call 'initialise_for_scheme (dynamic-link "guile_index.so.1"))
; 
; And then anyone wanting to use the module would say:
; 
; (use-modules (index))

A couple of things. 

- New modules probably shouldn't go into the root namespace if it can
be helped.  For example, matrix should probably be '(math matrix), and
people can then write (eg) '(math fft) '(math jacal) etc...

- Your compiled code doesn't actually need a scheme wrapper.  Suppose
you are creating a module '(database index).  Then in the C code, you
would have a function like
void 
scm_init_database_index_module()
{
	scm_register_module_xxx("database index", initialise_for_scheme);
}
You'd then compile this to produce libindex.so, which you would toss
into <somewhwere-on-%load-path>/database/libindex.so. Then
(use-modules (database index)) would dynamically load and initialize
the module. 

; > .lo and .la files are used by libtool. Hmm, generally when I need
; > shared lib, I just write automakefile (that's Makefile.am) and handle
; > compilation from there. Now, you need .so files to link with Guile, so
; > you call dynamic-link with install path and make sure that the .so is
; > always installed before running Guile.
; > 
; > This works, but makes compile cycle longer (by copying the files).
; 
; Well how does my method sound?
; If it's simple enough that I can understand it then it's gotta
; have some advantages.

Your method works fine, but isn't portable.  It is foreseen that guile
will be ble to read .la files and find the real .so files in a way
that appears operating-system independent.  Then your code will work on
non-Linux systems.  

So, in short:
- You're right; making dynamic libraries allows them to be independent
of libguile.  An example of this (was) libtcltk, which you could load
into your own hacked version of guile.  Another (I believe) is
the readline module --- if somebody gives you a guile prompt without
line editing, you can just suck in libreadline. 
- You can avoid having scheme wrappers and calling "dynamic-link" by
providing an appropriately-named function which calls
scm_register_module_xxx (or some approximation of this name; sorry)
- You should use automake and libtool for distributions; they don't
affect the installation or the dynamic linking, just the build
process.  I think if you're used to automake, it's easier to write
Makefile.in than Makefiles. 

Andrew
aarchiba@undergrad.math.uwaterloo.ca