2013-01-21 30 views
5

Sono nuovo al C, mi dispiace per la mia mancanza di conoscenza (il mio C-book qui è davvero enorme :)Estendi una libreria condivisa collegata dinamica?

Mi piacerebbe estendere una libreria condivisa (libcustomer.so) con sorgente chiusa, ma pubblica api conosciute.

È possibile qualcosa del genere?

  1. rinomina libcustomer.so a liboldcustomer.so
  2. creare un libcustomer.so libreria condivisa estesa (in modo che altri usano implicitamente la distesa)
  3. collegamento liboldcustomer.so nel mio estesa libcustomer.so via -loldcustomer
  4. inoltrare eventuali metodi non aggiuntivi attuate direttamente al vecchio "liboldcustomer.so"

non credo che avrebbe funzionato in questo modo (il nome è compilato nel .so, non è vero?). Ma qual è l'alternativa?

Per # 4: c'è un modo generale per farlo, oppure devo scrivere un metodo chiamato come il vecchio e inoltrare la chiamata (come?)?

Poiché il libcustomer.so (= liboldcustomer.so) originale può cambiare di volta in volta, tutta quella roba dovrebbe funzionare in modo dinamico.

Per motivi di sicurezza, il nostro sistema non ha LD_PRELOAD (altrimenti avrei prendere quel :().

Pensateci Extended Validation controlli & alcuni meglio NPE-Handlings.

Grazie in anticipo per il vostro aiuto !

EDIT:

sto solo attuare la mia estensione come indicato nella risposta, ma io ho un caso non gestita in questo momento:

Come posso "proxy" le strutture dalla libreria estesa?

Per esempio io ho questo:

customer.h:

struct customer; 

customer.c:

struct customer { 
    int children:1; 
    int age; 
    struct house *house_config; 
}; 

Ora, nel mio cliente extension.c sto scrivendo tutto il metodi pubblici formano customer.c, ma come faccio a "passare-attraverso" le strutture?

Molte grazie per il tuo tempo & aiuto!

+0

La risposta per la prima domanda aggiuntiva è già stata fornita. Il secondo è strettamente correlato - C/C++ non contiene alcuna metainformazione binaria, come Java/.NET, quindi non è possibile indovinare come potrebbe apparire la definizione di una struttura "cliente". Anche se ricordi i tipi e i nomi dei campi in questa struttura, potrebbero esserci problemi con le impostazioni del compilatore, ad esempio l'allineamento dei campi. –

+0

Ok, grazie. Ora proverò la risposta inviata :) –

risposta

5

in modo da avere OldLib con

void func1(); 
int func2(); 
... etc 

Il passo 4 potrebbe apparire come la creazione di un'altra libreria con un po 'di inizializzazione statico.

Creare newlib con contenuti:

void your_func1(); 

void (*old_func1_ptr)() = NULL; 
int (*old_func2_ptr)() = NULL; 

void func1() 
{ 
    // in case you don't have static initializers, implement lazy loading 
    if(!old_func1_ptr) 
    { 
     void* lib = dlopen("OldLibFileName.so", RTLD_NOW); 
     old_func1_ptr = dlsym(lib, "func1"); 
    } 

    old_func1_ptr(); 
} 

int func2() 
{ 
    return old_func2_ptr(); 
} 

// gcc extension, static initializer - will be called on .so's load 
// If this is not supported, then you should call this function 
// manually after loading the NewLib.so in your program. 
// If the user of OldLib.so is not _your_ program, 
// then implement lazy-loading in func1, func2 etc. - check function pointers for being NULL 
// and do the dlopen/dlsym calls there. 
__attribute__((constructor)) 
void static_global_init() 
{ 
    // use dlfcn.h 
    void* lib = dlopen("OldLibFileName.so", RTLD_NOW); 

    old_func1_ptr = dlsym(lib, "func1"); 
    ... 
} 

Il static_global_init e tutti i func_ptr 's può essere generata automaticamente se avete qualche descrizione della vecchia API. Dopo la creazione di NewLib, è possibile sostituire OldLib.

+0

Oh, è fantastico! Ci proverò domani sera e darò un feedback. Grazie mille :) –

+0

Prego. E devo anche ammettere che hai (quasi) scritto la risposta da solo :) –

+0

Tecnica di caricamento dinamico molto interessante! – loretoparisi

Problemi correlati