Domanda

Ho un'applicazione di cui una parte utilizza le librerie condivise. Queste librerie sono legati al momento della compilazione.
In fase di esecuzione il caricatore si aspetta che l'oggetto condiviso per essere nel LD_LIBRARY_PATH, se non si trova l'intero applicazione si blocca con l'errore "Impossibile caricare librerie condivise" .Si noti che non v'è alcuna garanzia che il cliente sarebbe avere la biblioteca, in quel caso voglio l'applicazione per lasciare un messaggio di errore adeguato anche la parte indipendente dovrebbe funzionare correttamente.

A questo scopo sto usando dlsym() e dlopen() di utilizzare l'API nella libreria condivisa. Il problema di questo è se ho un sacco di funzioni API, devo accedervi autonomamente utilizzando <=> e PTR che nel mio caso stanno portando alla memoria di corruzione e di codici a crash.

Ci sono alternative a questo?

È stato utile?

Soluzione

La soluzione comune al vostro problema è dichiarare una tabella di puntatori a funzione, per fare un solo dlsym () per trovarlo, e quindi chiamare tutte le altre funzioni tramite un puntatore a quel tavolo. Esempio (non testata):

// 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. Accesso ai funzioni API singolarmente utilizzando dlsym e puntatori non di per sé portare alla corruzione della memoria e si schianta. Molto probabilmente avete appena bug.

EDIT:
È possibile utilizzare questa stessa tecnica esatta con una libreria di terze parti. Creare un libdrmaa_wrapper.so e mettere il api_table in esso. Collegare l'involucro direttamente contro libdrmaa.so.

Nel eseguibile principale, dlopen("libdrmaa_wrapper.so", RTLD_NOW). Questo dlopen avrà successo se (e solo se) dlsym è presente in fase di esecuzione e fornisce tutte le funzioni API utilizzate nel <=>. Se non riesce, una singola chiamata <=> ti darà accesso a tutta l'API.

Altri suggerimenti

È possibile avvolgere l'applicazione con un altro che controlla innanzitutto per tutte le librerie richieste, e se manca qualcosa che gli errori fuori bene, ma se tutto va per il meglio che i dirigenti l'applicazione reale.

L'uso di sotto tipo di codice

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

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

utilizzare dlopen() per caricare questa libreria in fase di esecuzione. e utilizzare dlsym() e chiamare getDynLibPointer() che restituisce oggetto DynLib. da questo oggetto è possibile accedere a tutte le funzioni JST come obj.fun1() .....

Questa è ofcource uno stile C ++ del metodo di struct proposto in precedenza.

Si sono probabilmente alla ricerca di una qualche forma di carico biblioteca ritardo su Linux. Non è disponibile out-of-the-box, ma si può facilmente imitare con la creazione di una piccola biblioteca stub statica che avrebbe cercato di dlopen libreria richiesta in prima convocazione a qualsiasi delle sue funzioni (che emettono messaggio di diagnostica e chiude se <=> fallito) e quindi inoltrare tutte le chiamate ad esso.

Queste librerie stub possono essere scritti a mano, generato dal progetto script / specifiche biblioteca o generato da strumento universale Implib.so :

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

Il tuo problema è che la risoluzione dei simboli irrisolti è fatto molto presto - su Linux Credo che i simboli di dati sono risolti in fase di avvio di processo, ei simboli di funzione sono fatto pigramente. Quindi a seconda di ciò che hai simboli irrisolti, e che tipo di inizializzazione statico che avete in corso -. Non si può avere la possibilità di entrare in con il codice

Il mio suggerimento sarebbe quello di avere un applicazione wrapper che intrappola la stringa di codice di ritorno / di errore "Impossibile caricare librerie condivise", e quindi lo converte in qualcosa di più significativo. Se questo è generico, non ha bisogno di essere aggiornato ogni volta che si aggiunge una nuova libreria condivisa.

In alternativa si potrebbe avere il vostro involucro Esegui script ldd e poi analizzare l'output, <=> segnalerà tutte le librerie che non si trovano per una particolare applicazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top