Edited from some email between Todd and Greg, 10 October 1998 -- jtl First, an overview of how to create a dynamic module: ----------------------------------------------------- Suppose you have some scwm code, written just like any other scwm .c file, that you want to be a dynamically loaded modules (app scwm foo). The module is implemented by a C file bar.c. (In most cases, 'foo' and 'bar' would probably be the same; I'm using separate names to try to clarify the separation some.) You would create a directory scwm/modules/foo, and put bar.c in it. Add 'foo' to the SUBDIRS in scwm/modules/Makefile.am (would be nice if that were automated). Add "modules/foo/Makefile" to the AC_OUTPUT list at the end of scwm/configure.in. Create a file scwm/modules/foo/Makefile.am like so: ----- scwm_module_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = bar.c libfoo_la_LDFLAGS = -export-dynamic libfoo_snarfs = bar.x INCLUDES = -I$(top_srcdir)/scwm @x_cflags@ @GUILE_INCLUDES@ @CASSOWARY_INCLUDES@ BUILT_SOURCES = $(libfoo_snarfs) SUFFIXES = .x # just use `make CC=g++' and the revised guile-snarf which uses ${CC} will work # for C++ prototype extraction %.x: %.c guile-snarf $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $< > $@ %.x: %.cc CC=$(CXX) \ guile-snarf $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS) $< > $@ ETAGS_ARGS = --regex='/[ \t]*SCM_SYMBOL[ \t]*(\([^,]*\)/\1/' --regex='/[ \t]*SCWM_PROC[ \t]*(\([^,]*\),[^,]*/\1/' ------ The %.x: %.cc can be removed if there's no C++, but it doesn't hurt to leave it in. At some point, all of that from 'SUFFIXES = .x' down should probably go into a template, and the rest could be autogenerated. The bar.c and bar.x have to match each other. The libfoo.la has to match the name of the module. Your .c file, being a mostly-standard scwm .c file, already has a void init_bar() function. This can be made static. Create a new function: void scm_init_app_scwm_foo_module() { scm_register_module_xxx("app scwm foo", init_bar); } the 'foo' in the name and string need to match the module name, and also needs to match the library name given in Makefile.am. The init_bar is a pointer to your old initialization function. The _xxx is literal, not standing for anything else. Note that dashes in the module name turn into underscores in the init function name (e.g., for (apps scwm xpm-menus) we use scm_init_app_scwm_xpm_menus_module) -- see below. re-autogen, and make and install as normal. If you're compiling in an already-compiled-in tree, you may need to make twice for the .x file to be created. I see this with non-modules too, and don't think it's something broken in the modules system, but something broken in general. That's it, you have a dynamically loaded module! ----------------------------------------------------- Now, for some miscellaneous amplifications and explanations. > How does this function: > > void scm_init_app_scwm_xpm_menus_module() > { > scm_register_module_xxx("app scwm xpm-menus", init_draw_xpm_menu); > } > > get invoked? Guile has magic to invoke functions named after the module like that. In the guile-ref info file, look at the "Dynamic Linking and Compiled Code Modules" node, especially the part talking about a 'module init function'. Basically, replace the spaces in the full module name ("app scwm foo") with undescores (the hyphens also; this is experimentally derived, not in the guile documentation), preceed it with "scm_init_" and follow it with "_module", and you have the name of a function that guile knows to call to import the module. There's no reason I know of for the object code needs to be dynamically loaded for this to work. If you resturcture the code to look like: static void real_init_bar() { /* whatever else needs to be done for this module */ #ifndef SCM_MAGIC_SNARFER #include "bar.x" #endif } void scm_init_foo_module() { scm_register_module_xxx("app scwm foo", real_init_bar); } void init_bar() { scm_register_module_xxx("app scwm foo", real_init_bar); } then bar.c can be linked in either statically or dynamically, and (use-modules (app scwm foo)) will import the public symbols it defines. The build issues are tricky for that; if we decide we want to be able to do it, we may want to reconsider the modules source-tree split. If you're very interested, you should read the libtool documentation and the guile-ref dynamic module section. Thanks to the wonderful job libtool and guile do insulating us from all the system-specific vagaries of dynamic objects, though, I don't think you really need to read either of those to create modules. There's no reason you can't have more than one source file to implement the module. Just add any aditional .c files to the libfoo_la_SOURCES line, and they'll get linked in. If they define any scheme symbols, add a .x entry for them in libfoo_snarfs, and their init funcs need to be called, directly or indirectly, under the scm_register_module_xxx.