first stab at module system

Bill Gribble grib@linuxdevel.com
Tue, 3 Jul 2001 21:56:10 -0500


I have developed a simple module/plugin system, intended for Gnucash,
based on dlopen, and I'm hoping to get some feedback on my "sample
implementation". I've put the source code up at ftp.linuxdevel.com in
/pub/gnc-module.tar.gz.  Have a look.

The main thing is src/gnc-module.c, which provides the load and unload
functions from C.  It's g-wrapped so you can do it from Scheme.  A
"gnc-module" is a C .so library that has a function "void
gnc_module_init(void)".  By convention, that function does anything
necessary to load g-wrapped and other Scheme modules.  gnc_module_init
gets called the first time the module is loaded.

For the backends, which are already dynamically loaded, this framework
is mostly irrelevant; it will require a little renaming of dlopen to
gnc_module_load and dlsym to gnc_module_lookup, but other than that
nothing will change.  The main impact will be on the adding of new
plugins and the refactoring of the current code base into a collection
of "core modules".

The tests in test/ (run with 'make check' at the top level)
demonstrate loading modules (from the mod-foo, mod-bar, and mod-baz
directories) from C and Scheme and calling functions in them.  In
particular, look at mod-baz and the test that uses it
(test-load-deps.{c,scm}).

In this test, mod-baz is the equivalent of the register or another
module that depends on a more primitive module (in this case mod-foo,
in gnucash the engine).  It is built by directly linking against
libfoo.so so that the source code for libbaz.so doesn't have to be
modified to use it with the module system.  The idea is that we could
make the register and the engine separate modules but not have to
modify the code of either.  Loading the register would ensure that the
engine got loaded too.

The overall purpose of the module system is threefold:

  - one, to give the core parts of Gnucash a finer granularity so that
  we can build versions of gnucash that have no GUI or an alternate
  GUI

  - two, to break up the source code into more-or-less coherent
  "units" of C, Scheme, g-wrap definitions, and Glade files that are
  managable and understandable, so that more developers will be able
  to participate in Gnucash development
  
  - three, to allow people that want "special purpose" functionality
  for gnucash, such as small business modules, to be able to write
  plugins that don't have to be loaded by "normal" users, and to
  provide an easy way for people to add new functions to Gnucash
  without having to grok the whole code base

The system as it stands is unfinished, but it allows you to collect C
code, g-wrap function definitions, and Scheme modules together in one
source code directory, and to load it all with one function call from
C or Scheme.

If people like the basic idea, the next step is to start moving the
source code around to split up 'gnc.gwp' and 'gnc-dialogs.glade' into
module-specific pieces, to group related C and Scheme code together,
and to change the startup process to be a much simpler wrapper that
just loads a bunch of modules.

After that, we need to start identifying places in Gnucash where new
behaviors might be "poked" by runtime-loaded plugins and add API to
make those behaviors configurable.  The HTML processing subsystem does
this now, for example, allowing new <object> handlers and form submit
methods to be poked into its tables.  We also need to find top-level
data structures, like the application menus, that should be modifiable
by plugins and publish an API to do so.

Any feedback appreciated,
b.g.