2011-01-12 6 views
8

Aufgrund einiger Einschränkungen bin ich gezwungen, eine in C geschriebene Bibliothek zur Laufzeit zu laden. Eine dritte Partei stellt mir zwei Bibliotheken als statische Archive zur Verfügung, die wir zu gemeinsamen Objekten machen. Die Anwendung, mit der ich arbeite, lädt eine der Bibliotheken zur Laufzeit basierend auf einigen Hardware-Parametern. Leider ist eine der Bibliotheken weitgehend mit globalen Variablen konfiguriert.dlopen und globale Variablen in C/C++

Ich verwende bereits dlsym, um Funktionsreferenzen zu laden, aber kann ich dlsym auch verwenden, um Verweise auf diese globalen Variablen zu laden?

Antwort

10

Ja, Sie können dlsym verwenden, um auf Globals zuzugreifen (solange sie exportiert werden und nicht statisch sind). Das folgende Beispiel ist in C++ und Mac, aber offensichtlich funktioniert C gut.

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

Ausgang:

% ./a.out 
12 
+0

Und selbst wenn Sie C++ - Bibliothek aus C-Laufzeit laden, werden alle Ihre globalen Objekte konstruiert! Und zerstört, wenn du es entlädst – yanpas

1

Ja, Sie können jedes exportierte Symbol in der dynamischen Bibliothek unter Verwendung von dlsym() finden.

1

Ja, Sie können, und ich eigentlich bevorzuge dies, anstatt Funktionen zu laden. Mein Standard-IOC-Modell macht es so.

ziehe ich es, weil:

  • Die Besetzung von einem void * auf einen Zeiger auf ein Objekt als die technisch sicherer ist, zu einem Funktionszeiger, obwohl natürlich das System, das * mit dlsym Leere verwendet ermöglichen muß Sie konvertieren den Zeiger. (GetProcAddress von Microsoft gibt ihren eigenen Zeigertyp zurück, was in diesem Fall meiner Meinung nach eine bessere Wahl ist, da sie die tatsächliche Bedeutung später ändern können, wenn sie es benötigen).

  • Da ich es in C++ mache, kann ich erzwingen, dass jedes solche exportierte Objekt von einer gemeinsamen Basisklasse abgeleitet wird, und dann kann ich dynamic_cast von dieser Klasse zu der tatsächlichen verwenden, die ich erwarte. Dies bedeutet, dass ich einen Fehler finden kann, wenn er nicht von der späteren Klasse abgeleitet ist, und später Laufzeitfehler speichern.