Popola puntatori a funzione globali in libreria condivisa (Solaris, Sun Studio)
-
26-10-2019 - |
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:
- Se lo faccio in questo modo, quando sono questi puntatori popolate?
- Posso loro assumere per essere caricati nel mio eseguibile che carica questa libreria?
- 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
- 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.
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.