Domanda

Sto creando una piccola C ++ involucro libreria condivisa attorno ad una libreria di Fortran 95. Dal momento che i simboli Fortran contengono . nel nome del simbolo, devo usare dlsym per caricare la funzione Fortran in un puntatore a funzione C ++.

Attualmente, ho un sacco di puntatori a funzione globali nei file di intestazione:

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

e Io popolo nel file corrispondente C ++:

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

Domande:

  1. Se lo faccio in questo modo, quando sono questi puntatori popolate?
  2. Posso loro assumere per essere caricati nel mio eseguibile che carica questa libreria?
  3. In particolare, Posso utilizzare queste funzioni in oggetti creati staticamente nei miei eseguibili o di altre librerie? Oppure questo soffre di ordine inizializzazione del statico fiasco
  4. Se il modo di cui sopra non è corretto, qual è il modo più elegante di popolare questi puntatori in modo tale che essi possono essere utilizzati in oggetti statici in eseguibili e altre librerie?

Sto usando il compilatore Sun Studio su Solaris, se questo fa la differenza, ma vorrei anche essere interessati a una soluzione per GCC su Linux.

È stato utile?

Soluzione

Da dove viene la riga

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

verificarsi in test.cc? Il puntatore verrà inizializzato quando la linea è eseguito (che ovviamente dipende da quando la funzione che lo contiene è chiamato). O hai intenzione di scrivere

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

? In questo caso, il puntatore viene inizializzato durante statico inizializzazione. Il che significa che avete ancora ordine di inizializzazione problemi se si tenta di utilizzare i puntatori nel costruttore di una statica oggetto.

La soluzione classica per questo sarebbe di utilizzare una sorta di Singleton:

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...
{
}

Poi avvolgere la libreria in una classe C ++ che utilizza questa struttura per ottenere gli indirizzi dei puntatori.

E un'ultima osservazione: la reinterpret_cast si sta cercando di fare non è legale, almeno non formalmente. (Credo che sia Sun CC e g ++ volontà accettarlo, però.) Secondo Posix, il modo corretto per ottenere un puntatore a funzione dal dlsym potrebbe essere:

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

Ciò non si presta ad inizializzazioni, tuttavia.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top