2013-01-21 9 views
5

Jestem nowa w C, więc przepraszam za mój brak wiedzy (moja C-book tutaj jest naprawdę ogromna :)Rozszerzanie dynamicznie połączonej biblioteki współużytkowanej?

Chciałbym rozszerzyć biblioteki współdzielonej (libcustomer.so) z zamkniętego źródła, ale publiczne znany api.

Czy coś takiego jest możliwe?

  1. rename libcustomer.so do liboldcustomer.so
  2. utworzyć rozszerzoną libcustomer.so dzielone biblioteki (tak inni pośrednio korzystania z przedłużony jeden)
  3. odnośnik liboldcustomer.so na mój rozszerzony libcustomer.so poprzez -loldcustomer
  4. przekazania żadnych dodatkowych nie realizowanych metod bezpośrednio do starego „liboldcustomer.so”

nie sądzę, że to działa w ten sposób (nazwa jest kompilowany do .so, prawda?). Ale jaka jest alternatywa?

Dla # 4: czy istnieje ogólny sposób, aby to zrobić, czy muszę napisać metodę o nazwie takiej jak stara i przekazać dalej (jak?)?

Ponieważ oryginalny libcustomer.so (= liboldcustomer.so) może się zmieniać od czasu do czasu, wszystkie te rzeczy powinny działać dynamicznie.

Ze względów bezpieczeństwa, nasz system ma LD_PRELOAD (inaczej bym wziąć to :().

Pomyśl o Extended Validation kontrole & niektóre lepsze NPE-manipulacyjny.

Z góry dzięki za pomoc !

EDIT:

ja tylko wdrożenie mojego rozszerzenia, jak pokazano na odpowiedź, ale mam jedno nieobsługiwany sprawę w tej chwili:

Jak mogę "proxy" struktury z rozszerzonej biblioteki?

Na przykład mam to:

customer.h:

struct customer; 

customer.c:

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

Teraz, mój klient-extension.c piszę wszystko publiczne metody tworzą customer.c, ale jak mam "przekazywać" struktury?

Wielkie dzięki za poświęcony czas & pomoc!

+0

Odpowiedź na pierwsze dodatkowe pytanie już udzielono. Drugi jest blisko spokrewniony - C/C++ nie zawiera żadnych metainformacji binarnych, takich jak Java/.NET, więc nie możesz zgadnąć, jak mogłaby wyglądać definicja struktury "klienta". Nawet jeśli pamiętasz typy i nazwy pól w tej strukturze, mogą wystąpić problemy z ustawieniami kompilatora - np. Wyrównanie pola. –

+0

OK, dziękuję. Spróbuję teraz opublikowanej odpowiedzi :) –

Odpowiedz

5

Więc trzeba OldLib z

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

kroku 4 może wyglądać tworzenie innej biblioteki z pewnym statycznym inicjalizacji.

Tworzenie newlib o treści:

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"); 
    ... 
} 

static_global_init i wszystkie func_ptr „s może być wygenerowany automatycznie, jeśli masz jakiś opis starego API. Po utworzeniu NewLib z pewnością możesz zastąpić OldLib.

+0

To fantastyczne! Spróbuję tego jutro wieczorem i udzielę informacji zwrotnej. Dziękuję bardzo :) –

+0

Nie ma za co. I muszę też przyznać, że sam (prawie) napisałeś odpowiedź samemu :) –

+0

Bardzo interesująca technika dynamicznego ładowania! – loretoparisi

Powiązane problemy