Dynamic Loading of Modules (was: Back on the list)

Niklas Elmqvist d97elm at dtek.chalmers.se
Tue Feb 24 09:18:59 CET 1998


On Mon, 23 Feb 1998 coder at ibm.net wrote:
> On 20/02/98 at 12:43 AM, Niklas Elmqvist <d97elm at dtek.chalmers.se> said:
> >Nothing sensational,
> >it's all been done before, but I could outline my little scheme here if
> >there is interest.
> 
> Please do.

Okay, here goes...

As I said earlier, I am aiming to decouple the actual core server from
the world processing routines. Ideally, the main server would not even
*know* it is running a MUD, it would be sort of a general-purpose core,
and all the functionality such as DB management, socket I/O and AI would
be implemented in free-standing modules separate from the main executable
(at least, I envisioned this in the beginning). I mentioned this to a RL
friend of mine, and he pointed out that it all sounded very much like
conventional OS architecture, especially like the module system of Linux
kernels. I studied these a bit and learned some good stuff about dynamic
loading (or linking), and then started experimenting with using DL
together with C++. The results can be found at  
<URL:http://artoo.hemmet.s-hem.chalmers.se/~crozius/resources.html>, but I
will outline it briefly here as well.

In essence, what I discovered (to myself, that is, this is no doubt old
news to some people) was that I could compile the core server with a base
class with very little functionality, call it aClass, which called a
factory function in a shared library, returning a pointer to an aClass
object. Then, in the actual shared library (which is linked in with the
main binary at run-time) I instead return an instance of a class
called bClass, which inherits from aClass but which is totally unknown to
the core server. Best of all, it works! That is, when I call the Execute()
member function on the aClass handle in the core (which, unbeknowst to the
core, points to a bClass object with redefined Execute() function), the
correct Execute() function is called, that is bClass::Execute().

Now, if aClass and bClass had been part of the same binary, I would not
have been surprised. In fact, as you probably all know, this is called
late binding in the O-O community and is an important feature of all
serious O-O languages. However, what surprised and delighted me is that
late binding *still* works even though the core and shared lib described
above are separately compiled, and the bClass is totally unknown to the
core! In my eyes, this is the ultimate test of late binding, and G++
pulled it off nicely! Incidentally, a friend (the one mentioned above)
later reported that this is impossible in Windows-style DLLs.

If you are wondering what the fuss is all about (or why this posting is
getting so long), let me just say this: One application of this could be
an Event class (in an event-driven system), whose base class is known to
the core server (allowing for it to check the priority and expiration of
the event, among other things), while the modules can inherit from the
base class and redefine it to suit their particular needs. I also plan on
using this technique for Handler objects which take care of things such as
socket I/O, parsing, DB managment, etc, and the good thing about it is
that I thus will be able to attach and detach the modules at run-time (to
remedy a bug, for example). If the base classes are correctly implemented,
the core will never even have to be recompiled and thus never rebooted
(not accounting for fatal bugs, that is <g>)!

Whew. Sorry if I babbled on a mite too much, but I hope this will be of
some use to someone. If you need more information, I will be glad to
provide it.

-- Niklas Elmqvist (d97elm at dtek.chalmers.se) ----------------------
"You can't trample infidels when you're a tortoise. I mean, all you 
 could do is give them a meaningful look."	 
	- Terry Pratchett, Small Gods





More information about the mud-dev-archive mailing list