Metamodules are
classes that are to be described in dynamic linked libraries and to be
explicitly loaded by an application core from a specified class API
signature. So, metamodules may be considered as API signed classes that
are able to be dynamically instanciated from a core application without
any explicit code resolution of the module on the core side, all based
on the c++ polymorphic mechanism.
    Because such objects should be instanciated from a core application, 
they must be described with dynamic metaclasses in
order the main code to be able to call some functions on the newly
linked and allocated class i.e. the vtable to be functional and the
code accessible.
    A metamodule derives the 
CSerialized declaration. It is also able to expand the serialization process to dynamic loaded modules with a core centralized dispatcher.
    Once the dynamic metamodule is metaclass described,
there is just one requirement for the generics to manage it : the
metamodule code should resolve a specific function that will be the
entry point of the explicit dynamic load process and will return the
metaclass of the described meta module. This function is introduced
with the following macro :
  
    
      | DECLARE_METAMODULE_EXPORT (class); | 
    
  
  
  
    metamodule export declaration and code resolution macro.
  
    
      class CMetaModule : public CSerialized 
{ 
    // instanciation section  
    public : 
       
        CMetaModule  
               
  (); 
        virtual ~CMetaModule        ()=0; 
       
        // generic metaclass association 
        SECTION_GENERIC_METACLASS; 
}; 
       
// metaclass and class tag declaration 
DECLARE_GENERIC_METACLASS ('mtmx', CMetaModule, CSerialized); | 
    
  
  
  
    There is no particular function handling on the
CMetaModule definition. It is just defined as a logical abstract base
class.
Meta Module Importer API
    The generics
CMetaModuleImporter class defines facilities to explicitly
import metamodules defined in dynamic linked libraries. The
imported definitions should derive the CMetaModule class and declare
the DECLARE_METAMODULE_EXPORT macro as exposed above.
 The application core should resolve the cmetaclass.h code
section. The modules should not include this code resolution as there
must be one and only one static 
metaclasses list in the whole binary target ! See the "
Compiling your own libgenerics based on
applications" section for details on how to build such meta modules and core importers applications.
 
  
    
      class CMetaModuleImporter : public CClass 
{ 
    // instanciation section 
    public : 
       
        CMetaModuleImporter
              
   (const CString &inLibraryPath, const CMetaClass
*inRequestedAPI=__metaclass(CMetaModule)); 
        virtual ~CMetaModuleImporter     (); 
       
    // general importer functions 
    public : 
       
        // linked library handle, its name 
        void *   
                
        GetLibHandle     
          () const; 
        CString   
               
       GetLibName       
         () const; 
       
    // loaded module access 
    public : 
       
        // loaded module metaclass
access; do not instanciate the module via the returned metaclass
attributes, prefer using 
        // the CMetaModuleImporter
defined functions to ensure a correct resource freeing when done with it 
        const CMetaClass
*       
GetModuleMetaClass    () const; 
       
        // instanciate the imported metamodule 
        CMetaModule *   
       
 InstanciateModule          (); 
       
        // delete the specified metamodule instance 
        void   
               
           
DeleteModule             
  (CMetaModule *&); 
       
    // static function 
    public : 
       
        // potential library names of the specified path 
        static CStrings   
           
GetLibNames            
   (const CString &inPath); 
       
    // protected section 
    protected : 
       
        // the loaded library name, its handle and the associated metaclass 
        CString   
               
      LibName; 
        void *   
               
        LibHandle; 
        CMetaClass *   
            LibMetaClass; 
       
        // the module instances 
        CMetaModules             LibMetaModules; 
         
        // public capsule description 
        SECTION_CAPSULE_METACLASS; 
}; 
       
// class tag and metaclass description 
DECLARE_CAPSULE_METACLASS ('mtmi', CMetaModuleImporter, CClass); | 
    
  
  
  
Sample code
    As example, consider a core application that
manipulates some shapes (here a rectangle or a circle) to draw them on
a dedicated widget. The core application introduces some common
functionnalities to specific shapes handled by metamodule code
resolution. The serialization is not demonstrated here. This could be
written with the followings :
  
    
      | core application based on a generic shape definition | 
      specific shapes handlers, metamodules definitions     | 
    
    
      main.c 
cshape.h 
cshape.c | 
      cshape.h 
crectangle.c 
ccircle.c | 
    
  
  
  
 g++ -o main -rdynamic `pkg-config --cflags libgenerics-1.2` main.c cshape.c `pkg-config --libs libgenerics-1.2`
 g++ -o crectangle.so -shared `pkg-config --cflags libgenerics-1.2` crectangle.c
 g++ -o ccircle.so -shared `pkg-config --cflags libgenerics-1.2` ccircle.c
"cshape.h"
 // this section is destinated to the core application and its metamodules definitions
 #include "cmetamodule.h"
 ...
    class CShape : public CMetaModule
    {
        CShape   
             ();
        virtual ~CShape    ();
        virtual  Draw        (GtkWidget *) =0;
        SECTION_GENERIC_METACLASS;
    };
    DECLARE_GENERIC_METACLASS ('shap', CShape, CMetaModule);
"cshape.c"
 // this code section should only be linked into the application core binary
 #include "cshape.h"
    RESOLVE_GENERIC_METACLASS (CShape);
    CShape::CShape () : CMetaModule ()
    { }
    CShape::~CShape ()
    { }
    
"crectangle.c"
 // this code section is unknown from the core application, we
define here a specific metamodule handling on a generic shape
 #include "cshape.h"
    class CRectangle : public CShape
    {
        public :
            CRectangle () : CShape () 
            { }
            virtual ~CRectangle   () 
            { }
            virtual void Draw  (GtkWidget *inGtkWidget)
            {
           
    printf ("CRectangle::Draw : drawing a rectangle on
the specified widget\n");
            }
            SECTION_DYNAMIC_METACLASS;
    };
    DECLARE_DYNAMIC_METACLASS ('rect', CRectangle, CShape);
    RESOLVE_DYNAMIC_METACLASS (CRectangle);
    DECLARE_METAMODULE_EXPORT (CRectangle);
"ccircle.c"
 // this code section is unknown from the core application, we
define here a specific metamodule handling on a generic shape
 #include "cshape.h"
    class CCircle : public CShape
    {
        public :
            CCircle () : CShape () 
            { }
            virtual ~CCircle   () 
            { }
            virtual void Draw  (GtkWidget *inGtkWidget)
            {
           
    printf ("CCircle::Draw : drawing a circle on the
specified widget\n");
            }
            SECTION_DYNAMIC_METACLASS;
    };
    DECLARE_DYNAMIC_METACLASS ('circ', CCircle, CShape);
    RESOLVE_DYNAMIC_METACLASS (CCircle);
    DECLARE_METAMODULE_EXPORT (CCircle);
 
"main.c"
  // this section code is the core application wich loads the
specific metamodule shapes handlers without knowing their explicit
content
  #include "cshape.h"
  #include "cmetamoduleimporter.h"
  ...
  int main (int, char **)
  {
    // get the list of the potential metamodule
libraries names that should be in a "shapes" subdirectory in this sample
    CStrings inMetaModuleNames (CMetaModuleImporter::GetLibNames (CString("./shapes")));
    // declare a list of meta module importers, one for each metamodule
    TBuffer <CMetaModuleImporter *> theMetaModuleImporters;
    // foreach given library name, instanciate an importer
    for (size_t i=0; i<inMetaModuleNames.GetLength(); i++)
    {
        // instanciate a new metamodule
importer and be sure to import a CShape derived module (exceptions are
not handled in this sample)
        theMetaModuleImporters +=
new CMetaModuleImporter (*inMetaModuleNames[i], __metaclass(CShape));
    }
    // foreach metamodule importer, instanciate the
associated metamodule and call the virtual Draw specific definition
    for (size_t i=0; i<theMetaModuleImporters.GetLength(); i++)
    {
        // we requested a CShape derived
metamodule to be dynamically linked, so cast the new metamodule instance
        CShape *inShape = static_cast
<CShape *> ((*theMetaModuleImporters[i]) ->
InstanciateModule());
        // call the specific function definition
        inShape -> Draw (OnAGtkWidget);
    }
    ...
    // delete the metamodule importers i.e.
automatically unlink the metamodule libraries and free the instinciated
metamodules
    for (size_t i=0; i<theMetaModuleImporters.GetLength(); i++) delete *theMetaModuleImporters[i];
    // ok
    return 0;
  }