Question

Je suis en train de créer un petit wrapper C ++ bibliothèque partagée autour d'une bibliothèque Fortran 95. Étant donné que les symboles Fortran contiennent . au nom de symbole, je dois utiliser dlsym pour charger la fonction Fortran dans un pointeur de fonction C ++.

À l'heure actuelle, j'ai un tas de pointeurs de fonctions globales dans les fichiers d'en-tête:

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

et je les remplir dans le fichier C ++ correspondant:

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

Questions:

  1. Si je le fais de cette façon, Quand ces pointeurs de population?
  2. Puis-je les prendre à charger dans mon exécutable qui se charge cette bibliothèque?
  3. En particulier, puis-je utiliser ces fonctions dans les objets créés statiquement dans mes exécutables ou d'autres bibliothèques? Ou est-ce souffrir de la ordre initalization statique fiasco
  4. Si la manière ci-dessus n'est pas correct, quelle est la manière la plus élégante de peuplant ces pointeurs de telle sorte qu'ils peuvent être utilisés dans les objets statiques dans executables et d'autres bibliothèques?

J'utilise le compilateur Sun Studio sur Solaris, si cela fait une différence, mais je voudrais aussi être intéressé par une solution pour GCC sous Linux.

Était-ce utile?

La solution

Si la ligne ne

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

se produire dans test.cc? Le pointeur sera initialisé lorsque la ligne est exécuté (qui bien sûr dépend du moment où la fonction qui contient est appelé). Ou avez-vous l'intention d'écrire

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

? Dans ce cas, le pointeur sera initialisé pendant statique l'initialisation. Ce qui signifie que vous avez toujours ordre d'initialisation des problèmes si vous essayez d'utiliser les pointeurs dans le constructeur d'une statique objet.

La solution classique pour ce serait d'utiliser une sorte 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...
{
}

wrap et la bibliothèque dans une classe C ++ qui utilise cette structure pour obtenir les adresses des pointeurs.

Et une dernière remarque: le reinterpret_cast vous essayez de faire est de ne pas juridique, du moins pas officiellement. (Je pense que les deux Sun CC et G ++ l'accepter, cependant.) Selon Posix, la bonne façon d'obtenir un pointeur vers une fonction de dlsym serait:

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

Cela ne se prête pas à initialisations, cependant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top