2. Il Problema

Talvolta uno sviluppatore può trovarsi nella posizione di dover caricare una libreria (ed usare le funzioni ivi contenute) a runtime; questo accade il più delle volte quando si sta sviluppando un plug-in di qualche tipo o un programma disegnato con una architettura modulare.

In C caricare una libreria è estremamente semplice (è sufficiente invocare le funzioni dlopen, dlsym e dlclose), mentre in C++ l'operazione è leggermente più complessa. Le difficoltà insite nel caricare dinamicamente una libreria C++ sono in parte dovute al processo di decorazione dei simboli di linking comunemente chiamato name mangling, ed in parte dovute al fatto che l'interfaccia di dlopen è stata implementata pensando in C e, conseguentemente, non offre una maniera appropriata di caricare classi.

Prima di illustrare come si caricano dinamicamente le librerie in C++, è appropriato analizzare il processo di name mangling in maggior dettaglio. Si continui la lettura, la spiegazione del processo di decorazione dei simboli è importante nel comprendere le ragioni del problema e come risolverle.

2.1. Name Mangling

In ogni programma C++ (o libreria, o object file), tutte le funzioni non dichiarate come static sono rappresentate nel file binario da simboli. Questi simboli sono speciali stringhe di testo che identificano unicamente una funzione nel programma, la libreria o l'object file.

In C il simbolo e il nome della funzione corrispondono: il simbolo della funzione strcpy è appunto strcpy, e così per ogni altro simbolo. Questo è possibile perché in C due funzioni non dichiarate come static devono necessariamente avere nomi distinti.

Siccome il linguaggio C++ permette l'overloading di una funzione (diverse versioni di una funzione avente il medesimo nome ma una differente lista di argomenti) ed include svariate funzionalità non presenti in C - come classi, funzioni che fanno parte di dette classi, la specifica di eccezioni - non è semplicemente possibile impiegare il solo nome della funzione come unico simbolo. Per risolvere questo problema, il C++ utilizza il cosiddetto meccanismo di name mangling, che trasforma il nome della funzione e tutte le informazioni necessarie (come il numero e la dimensione degli argomenti) in una stringa di testo così ingarbugliata che solo il compiler riesce a comprenderla. Il simbolo risultante per la funzione foo potrebbe ad esempio essere foo@4%6^ - o potrebbe non includere nemmeno la parola "foo".

Uno dei problemi risultanti dal processo di name mangling è che lo standard C++ (currently [ISO14882]) non definisce come i simboli debbano essere codificati. Di conseguenza, ogni compiler "decora" i simboli in maniera diversa, alcuni compiler hanno addirittura cambiato l'algoritmo di name mangling tra diverse release (famoso il caso di g++ 2.x e 3.x). Anche se aveste studiato i dettagli del processo di name mangling del vostro compiler (e quindi sareste in grado di caricare funzioni per mezzo di dlsym), questa soluzione risulterebbe funzionare solamente con quel particolare compiler, ed il meccanismo potrebbe non funzionare già con la prossima versione del medesimo.

2.2. Classi

Un altro problema dell'interfaccia definita da dlopen è la limitazione inerente nel fatto che la libreria supporta solamente il caricamento di funzioni. Ma in C++ una libreria spesso espone la definizione di classi da utilizzare nei nostri programmi. Ovviamente, per poter utilizzare queste ultime si deve essere in grado di istanziare le medesime, ma questo non è facilmente fattibile.