I am creating a small C++ wrapper shared library around a Fortran 95 library. Since the Fortran symbols contain .
in the symbol name, I have to use dlsym
to load the Fortran function into a C++ function pointer.
Currently, I have a bunch of global function pointers in header files:
// test.h
extern void (*f)(int* arg);
and I populate them in the corresponding C++ file:
// test.cc
void (*f))(int* = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");
Questions:
I am using the Sun Studio compiler on Solaris, if that makes a difference, but I would also be interested in a solution for GCC on Linux.
Where does the line
f = reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_"));
occur in test.cc
? The pointer will be initialized when the line is
executed (which of course depends on when the function which contains it
is called). Or did you mean to write
void (*f)(int* ) = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");
? In this case, the pointer will be initialized during static initialization. Which means that you still have order of initialization issues if you try to use the pointers in the constructor of a static object.
The classical solution for this would be to use some sort of 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...
{
}
Then wrap the library in a C++ class which uses this structure to get the addresses of the pointers.
And one last remark: the reinterpret_cast
you are trying to do isn't
legal, at least not formally. (I think that both Sun CC and g++ will
accept it, however.) According to Posix, the correct way to get a
pointer to function from dlsym
would be:
void (*f)(int* );
*reinterpret_cast<void**>(&f) = dlsym(...);
This doesn't lend itself to initializations, however.