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 TFactory::TFactory(const string &soLibPath) { try { /* Caricamento della SO / openSo(soLibPath); / Casting necessario per una corretta assegnazione * della funzione al relativo puntatore */ *(void *) (&builder) = dlsym(handler, “buildObject”); / Controlla che il Simbolo Cercato (“buildObject”) sia * stato trovato… / if ( builder == NULL ) { // Errore nel caricamento della funzione / …in caso negativo, lancia un TFactoryException */ string exceptionMessage(" ERROR: “); exceptionMessage += dlerror(); throw TFactoryException(exceptionMessage); } } catch ( TFactoryException &e ) { throw e; } cout « “ Plug-In Loaded. Library-Path: “«> }

/** Distruttore TFactory */ template TFactory::~TFactory() {}

/**

  • 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 void TFactory::closeSo() { if (handler) { dlclose(handler); handler = NULL; } }

#endif

Per una migliore lettura, consiglio un bel Cut&Paste, magari in qualche Beautifier…