Question

J'ai une application dont une partie utilise des bibliothèques partagées. Ces bibliothèques sont liées au moment de la compilation.
Lors de l'exécution du chargeur attend l'objet partagé soit dans le LD_LIBRARY_PATH, si pas trouvé l'application se bloque ensemble avec erreur « Impossible de charger les bibliothèques partagées » .Remarque qu'il n'y a aucune garantie que le client serait d'avoir la bibliothèque, dans ce cas Je veux l'application de laisser un message d'erreur approprié aussi la partie indépendante devrait fonctionner correctement.

A cet effet, je me sers et dlsym() d'utiliser l'dlopen() API dans la bibliothèque partagée. Le problème avec ceci est si j'ai beaucoup de fonctions de l'API, je dois y accéder individuellement à l'aide et REE qui <=> dans mon cas conduisent à la corruption de mémoire et plante code.

Y a-t-il des solutions de rechange pour cela?

Était-ce utile?

La solution

La solution commune à votre problème est de déclarer une table de pointeurs de fonction, faire une seule dlsym () pour le trouver, puis appeler toutes les autres fonctions par un pointeur sur cette table. Exemple (non testé):

// libfoo.h
struct APIs {
   void  (*api1)(void);
   void *(*api2)(int);
   long  (*api3)(int, void *);
};

// libfoo.cc
void fn1(void) { ... }
void *fn2(int) { ... }
long fn3(int, void *) { ... }

APIs api_table = { fn1, fn2, fn3 };


// client.cc
#include "libfoo.h"
...
  void *foo_handle = dlopen("libfoo.so", RTLD_LAZY);
  if (!foo_handle) {
     return false;            // library not present
  }
  APIs *table = dlsym(foo_handle, "api_table");
  table->api1();              // calls fn1
  void *p = table->api2(42);  // calls fn2
  long x = table->api3(1, p); // calls fn3

P.S. Accès à vos fonctions API individuellement à l'aide dlsym et pointeurs ne pas en lui-même conduire à la corruption de la mémoire et se bloque. Très probablement, vous avez juste des bugs.

EDIT:
Vous pouvez utiliser cette même technique exacte avec une bibliothèque 3ème partie. Créer une et mettre le libdrmaa_wrapper.so en elle api_table. Liez l'enveloppe directement contre libdrmaa.so.

Dans le fichier exécutable principal, dlopen("libdrmaa_wrapper.so", RTLD_NOW). Ce réussira si dlopen (et seulement si) est présent à dlsym l'exécution et fournit toutes les fonctions de l'API que vous avez utilisées dans le <=>. Si elle réussit, un seul appel vous donnera <=> accès à l'API entier.

Autres conseils

Vous pouvez envelopper votre application avec un autre qui vérifie d'abord pour toutes les bibliothèques nécessaires, et si quelque chose manque, il des erreurs à bien, mais si tout est Allright il EXECs l'application réelle.

Utilisation ci-dessous type de code

Class DynLib
{
    /* All your functions */
    void fun1() {};
    void fun2() {};
    .
    .
    .
}

DynLib* getDynLibPointer()
{
    DynLib* x = new Dynlib;
    return x;
}

utiliser pour charger cette dlopen() bibliothèque lors de l'exécution. et l'utilisation et appelez dlsym() qui retourne l'objet getDynLibPointer() DynLib. de cet objet, vous pouvez accéder à toutes vos fonctions JST comme obj.fun1() .....

Ceci est ofcource un style C ++ de la méthode struct proposée précédemment.

Vous cherchez probablement une certaine forme de charge de la bibliothèque de retard sur Linux. Ce n'est pas disponible hors-the-box, mais vous pouvez facilement imiter en créant une petite bibliothèque stub statique qui tenterait de la bibliothèque nécessaire sur dlopen premier appel à l'une des fonctions qu'il est (émettant un message de diagnostic et se terminant si <=> échoué), puis transmettre tous les appels à elle.

Ces bibliothèques stub peuvent être écrites à la main, générée par projet / script spécifique bibliothèque ou généré par l'outil universel Implib.so :

$ implib-gen.py libxyz.so
$ gcc myapp.c libxyz.tramp.S libxyz.init.c ...

Votre problème est que la résolution des symboles non résolus se fait très tôt - sous Linux, je crois que les symboles de données sont résolus au démarrage du processus, et les symboles de fonction sont fait paresseusement. Par conséquent, en fonction de ce que les symboles que vous avez en suspens, et sur quel type d'initialisation statique que vous avez en cours -. Vous ne pouvez pas obtenir une chance d'obtenir votre code

Ma suggestion serait d'avoir une application wrapper qui emprisonne la chaîne code de retour / erreur « Impossible de charger les bibliothèques partagées », et convertit cela en quelque chose de plus significatif. Si cela est générique, il ne sera pas besoin d'être mis à jour chaque fois que vous ajoutez une nouvelle bibliothèque partagée.

Sinon, vous pourriez avoir votre course script encapsulant puis analyser ldd la sortie, rapportera toutes <=> bibliothèques qui ne figurent pas pour votre application.

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