Generics Reference Manual

CClass
|-- CMetaModuleImporter
|-- CSerialized
    |-- CMetaModule

Meta Module Abstraction



    Meta Module Definition

    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;
  }