2011-01-12 3 views
8

A causa di alcune restrizioni, sono costretto a caricare una libreria scritta in C in fase di esecuzione. Una terza parte fornisce a me due librerie come archivi statici che trasformiamo in oggetti condivisi. L'applicazione con cui sto lavorando carica una delle librerie in fase di esecuzione sulla base di alcuni parametri hardware. Sfortunatamente una delle librerie è configurata in gran parte con variabili globali.variabili dlopen e globali in C/C++

Sto già utilizzando dlsym per caricare i riferimenti alle funzioni, ma posso usare dlsym per caricare anche riferimenti a queste variabili globali?

risposta

10

Sì, è possibile utilizzare dlsym per accedere a globals (purché siano esportati e non statici). L'esempio sotto è in C++ e Mac, ma ovviamente C funzionerà bene.

lib.cpp:

extern "C" { 
    int barleyCorn = 12; 
} 

uselib.cpp

#include <dlfcn.h> 
#include <iostream> 
using namespace std; 

main() 
{ 
    void * f = dlopen ("lib.dylib", RTLD_NOW); 
    void * obj = dlsym (f, "barleyCorn"); 
    int * ptr = (int *) obj; 
    cout << *ptr << endl; 
} 

uscita:

% ./a.out 
12 
+0

E anche se si carica la libreria C++ dal runtime C, verranno creati tutti gli oggetti globali! E distrutto quando lo scarichi – yanpas

1

Sì, è possibile individuare qualsiasi simbolo esportato nella libreria dinamica utilizzando dlsym().

1

Sì, è possibile e io in realtà preferisci farlo piuttosto che caricare le funzioni. Il mio modello IOC standard funziona in questo modo.

preferisco perché:

  • Il cast da un vuoto * a un puntatore a un oggetto è tecnicamente più sicuro rispetto a quella di un puntatore a funzione, anche se ovviamente il sistema che utilizza void con dlsym deve consentire per convertire il puntatore. (Il GetProcAddress di Microsoft restituisce il proprio tipo di puntatore, che in questo caso ritengo sia una scelta migliore in quanto possono cambiare il significato effettivo di questo in seguito, se necessario).

  • Perché lo faccio in C++, posso far sì che qualsiasi oggetto esportato derivi da una classe base comune, e quindi posso usare dynamic_cast da quella classe a quella che mi aspetto che sia. Ciò significa che posso rilevare un errore se non deriva dalla classe successiva, salvando in seguito gli errori di runtime.