Pregunta

Estoy creando una pequeña biblioteca compartida de envoltura C ++ alrededor de una biblioteca Fortran 95. Dado que los símbolos de Fortran contienen . En el nombre del símbolo, tengo que usar dlsym Para cargar la función FORTRAN en un puntero de la función C ++.

Actualmente, tengo un montón de punteros de funciones globales en archivos de encabezado:

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

y los pueblo en el archivo C ++ correspondiente:

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

Preguntas:

  1. Si lo hago de esta manera ¿Cuándo se poblan estos punteros?
  2. ¿Puedo asumir que se cargan en mi ejecutable que cargue esta biblioteca?
  3. En particular, ¿Puedo usar estas funciones en objetos creados estáticamente? en mi ejecutable u otras bibliotecas? O esto sufre de la Fiasco de orden de initalización estática?
  4. Si el camino anterior no es correcto, ¿Cuál es la forma más elegante de poblar estos punteros? ¿De tal manera que puedan usarse en objetos estáticos en ejecutables y otras bibliotecas?

Estoy usando el compilador Sun Studio en Solaris, si eso marca la diferencia, pero también estaría interesado en una solución para GCC en Linux.

¿Fue útil?

Solución

Donde esta la línea

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

ocurre en test.cc? El puntero se inicializará cuando se ejecute la línea (que, por supuesto, depende de cuándo se llama la función que se contiene). O quisiste escribir

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

? En este caso, el puntero se inicializará durante la inicialización estática. Lo que significa que todavía tiene problemas de inicialización si intenta usar los punteros en el constructor de un objeto estático.

La solución clásica para esto sería usar algún tipo de 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...
{
}

Luego envuelva la biblioteca en una clase C ++ que usa esta estructura para obtener las direcciones de los punteros.

Y un último comentario: el reinterpret_cast Estás tratando de hacer no es legal, al menos no formalmente. (Creo que tanto Sun CC como G ++ lo aceptarán.) Según Posix, la forma correcta de obtener un puntero para funcionar desde dlsym sería:

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

Sin embargo, esto no se presta a las inicializaciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top