The DynObj library depends on some conditions from the compiler and OS:
- There must be an API for loading shared modules/libraries and resolve symbols in them.
- There must be a shared calling convention for ordinary functions available
(such as __cdecl). There usually is, since C level linking would not
- The calling convention for virtual member function invocation must be
the same. (On GCC platforms this is so, and on Windows, one can explicitely
specify the one to use [we use the define docall for this]).
- The pointer to the table of virtual functions must be located first in
any plugin object. On modern C++ compilers this is usually the case. (C-front
based compilers from long ago typically did put it last).
Cross-Compiler Type Information
The interface query function T* do_cast<T>( U* pu ) is a key point
[this template function is a C++ wrapper around a C API]. It is what allows host
and plugins to use objects from other binaries in safe and useful ways.
To implement it, we must be able to:
The solution to the first points above is to have the plugin library generate
the required type information and make it avaialable at plugin load time.
- Have access to type information from the source compiler:
- We need some means of verifying that source and plugin compiler
agree on what functions an interface contains.
- We need to know where sub objects are located inside compound objects.
- We also need ways to determine the type of an arbitrary object of
which we only know that it is an object with 1 or more virtual functions.
The last point above is the subject of the next section.
VPTR and Virtual function tables
The VPTR is the first member of a binary object with virtual functions, pointing
to its virtual function table. And, if a type implements some methods on its
own, it must have its very own VTable. So, in effect, the VPTR is then a valid
type identifier value. This is quite a useful feature.
Virtual tables are built on loading code, so values of VPTR:s are not known
beforehand. We must rather discover them, and then store the VPTR:s into a
type table. Later in a do_cast operation, we can consult this table and
know what type we're dealing with.