Frage

Ich erstelle eine kleine C ++ - Wrapper Shared Library um eine FORTRAN 95 -Bibliothek. Da enthalten die Forran -Symbole . Im Symbolnamen muss ich verwenden dlsym So laden Sie die FORTRAN -Funktion in einen C ++ - Funktion Zeiger.

Derzeit habe ich eine Reihe globaler Funktionszeiger in Header -Dateien:

// test.h
extern void (*f)(int* arg);

Und ich bevölkern sie in der entsprechenden C ++: Datei:

// test.cc
void (*f))(int* = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");

Fragen:

  1. Wenn ich es so mache, Wann werden diese Zeiger besiedelt?
  2. Kann ich davon ausgehen, dass sie in meine ausführbare Datei geladen werden, die diese Bibliothek lädt?
  3. Im Speziellen, Kann ich diese Funktionen in staatlich erstellten Objekten verwenden? in meiner ausführbaren Datei oder anderen Bibliotheken? Oder leidet dies unter dem statische Initalisationsreihenfolge Fiasko?
  4. Wenn der oben genannte Weg nicht korrekt ist, Was ist die eleganteste Art, diese Zeiger zu bevölkern so dass sie in statischen Objekten in ausführbaren und anderen Bibliotheken verwendet werden können?

Ich benutze den Sun Studio -Compiler auf Solaris, wenn das einen Unterschied macht, aber ich würde mich auch für eine Lösung für GCC unter Linux interessieren.

War es hilfreich?

Lösung

Wohin geht die Linie?

f = reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_"));

auftreten in test.cc? Der Zeiger wird initialisiert, wenn die Zeile ausgeführt wird (was natürlich davon abhängt, wann die Funktion, die sie enthält, aufgerufen wird). Oder wollten Sie schreiben

void (*f)(int* ) = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");

? In diesem Fall wird der Zeiger während der statischen Initialisierung initialisiert. Dies bedeutet, dass Sie immer noch Probleme mit der Initialisierungsprobleme haben, wenn Sie versuchen, die Zeiger im Konstruktor eines statischen Objekts zu verwenden.

Die klassische Lösung dafür wäre, eine Art Singleton zu verwenden:

struct LibraryPointers
{
    void (*f)(int* );
    //  ...
    static LibraryPointers const& instance()
private:
    LibraryPointers();
};

LibraryPointers const&
LibraryPointers::instance()
{
    static LibraryPointers theOneAndOnly;
    return theOneAndOnly;
}

LibraryPointers::LibraryPointers()
    : f( reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_")) )
    , //  initialization of other pointers...
{
}

Wickeln Sie dann die Bibliothek in eine C ++ - Klasse, die diese Struktur verwendet, um die Adressen der Zeiger zu erhalten.

Und eine letzte Bemerkung: die reinterpret_cast Sie versuchen, nicht legal zu tun, zumindest nicht offiziell. (Ich denke, dass sowohl Sun CC als auch G ++ es jedoch akzeptieren werden.) Laut Possix die richtige Art, einen Zeiger zu erreichen dlsym wäre:

void (*f)(int* );
*reinterpret_cast<void**>(&f) = dlsym(...);

Dies eignet sich jedoch nicht für Initialisierungen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top