|
17.4 A Simple GNU/Linux Module Loader
Something to be aware of, is that when your users write dynamic modules
for your application, they are subject to the interface you design. It
is very important to design a dynamic module interface that is clean and
functional before other people start to write modules for your code. If
you ever need to change the interface, your users will need to rewrite
their modules. Of course you can carefully change the interface to
retain backwards compatibility to save your users the trouble of
rewriting their modules, but that is no substitute for designing a
good interface from the outset. If you do get it wrong, and
subsequently discover that the design you implemented is misconceived
(this is the voice of experience speaking!), you will be left with a
difficult choice: try to tweak the broken API so that it does work
while retaining backwards compatibility, and the maintenance and
performace penalty that brings? Or start again with a fresh design born
of the experience gained last time, and rewrite all of the modules you
have so far?
If there are other applications which have similar module requirements
to you, it is worth writing a loader that uses the same interface and
semantics. That way, you will (hopefully) be building from a known good
API design, and you will have access to all the modules for that
other application too, and vice versa.
For the sake of clarity, I have sidestepped any issues of API
design for the following example, by choosing this minimal interface:
- Function: int run (const char *argument)
- When the module is successfully loaded a function with the following
prototype is called with the argument given on the command line. If
this entry point is found and called, but returns `-1', an error
message is displayed by the calling program.
Here's a simplistic but complete dynamic module loading application you
can build for this interface with the GNU/Linux dynamic loading
API:
You would compile this on a GNU/Linux machine like so:
|
$ gcc -o simple-loader simple-loader.c -ldl
|
However, despite making reasonable effort with this loader, and ignoring
features which could easily be added, it still has some seemingly
insoluble problems:
-
It will fail if the user's platform doesn't have the
dlopen
API. This also includes platforms which have no shared libraries.
-
It relies on the implementation to provide a working self-opening
mechanism. `dlopen (NULL, RTLD_NOW)' is very often unimplemented,
or buggy, and without that, it is impossible to access the symbols of
the main program through the `dlsym' mechanism.
-
It is quite difficult to figure out at compile time whether the target
host needs `libdl.so' to be linked.
I will use GNU Autotools to tackle these problems in the next chapter.
|