Come avevo anticipato (o no?) ecco il codice della Factory che carica Classi a Run-Time (tipo Plug-In) in C++. E’ anche (indecentemente) commentata, quindi: divertitevi…
#ifndef TFACTORY_H #define TFACTORY_H #include “TFactoryException.h” #include <dlfcn.h> // Libreria “Dynamic Lynking Loader”</dlfcn.h>
/**
@class TFactory TFactory.h
Questa Classe Template ha il compito di @b Istanziare @b a @b Run-Time Classi
la cui Dichiarazione e Definizione non e’ avvenuta a @b Compile-Time.
In sostanza, si parla di realizzare un sistema per la gestione
di quelli che, in gergo, si chiamano @b Plug-In: mini-programmi che
si aggiungono ad altri piu’ grandi per aumentarne le funzionalita'.
E’ una “Factory” di Classi @a Plug-In.
Carica da libreria SO la definizione di una Classe che ha come
Classe di Base il Parametro passato alla Factory: in questo modo e'
sufficiente, per realizzare classi Plug-In, che le Classi da Istanziare
a Run-Time implementino un’interfaccia comune.
Per la precisione, e’ anche necessario che nella libreria SO che
contiene la classe sia presente una funzione cosÏ definita:
extern “C”
*buildObject(void) { return new ; } @c buildObject(void) crea effettivamente una istanza della Classe Plug-In.
Questa soluzione permette quindi di caricare nuove Classi senza
bisogno ne di ricompilare, ne di modificare il codice. */ template
class TFactory { public: TFactory(const string &); ~TFactory(); T build () ; void closeSo(); private: /* Handler della SO caricata */ void handler; / Puntatore alla funzione (o, meglio, al “simbolo”) * ritornato da “dlsym” */ T (*builder)(void); void openSo(const string &); };
/**
- Costruttore TFactory.
- Si occupa anche di recuperare i Simboli (@c “buildObject” )
- necessari all’istanziazione di una nuova T Class.
- @param soLibPath Path alla Libreria SO da dove caricare la definizione
della Classe */
template
/** Distruttore TFactory */
template
/**
- Restituisce una istanza della Classe contenuta nella SO.
- L’oggetto restituito e’ UP-Castato alla Classe Base “T”
- (parametro del Template)
- @return Una nuova istanza di T (T = Parametro di TFactory) */
template
T TFactory ::build() { return ( (*builder)() ); // Ritorna la nuova istanza di T }
/**
Carica la libreria SO.
@param soLibPath Libreria SO da caricare / template
void TFactory ::openSo(const string &soLibPath) { / Apertura della Libreria SO */ handler = dlopen( soLibPath.data(), RTLD_NOW);if (!handler) { string exceptionMessage("
ERROR: “); exceptionMessage += dlerror(); throw TFactoryException(exceptionMessage); } }
/** Chiude la libreria SO */
template
#endif
Per una migliore lettura, consiglio un bel Cut&Paste, magari in qualche Beautifier…