2012-07-30 17 views
6

Próbuję zbudować bibliotekę współdzieloną przy użyciu gcc 4.6 w systemie Linux, który jest ładowany dynamicznie. Jak opisano w wielu artykułach w Internecie, jak również w poprzednich pytaniach, udostępniam w bibliotece metody fabryczne w stylu c do tworzenia i niszczenia obiektów. Kod - w minimalnej postaci - wygląda następująco:Niezdefiniowany symbol "typeinfo" z dynamicznie ładowaną biblioteką

base.h:

class base { 
public: 
    base(); 
    virtual ~base(); 
    virtual int value() = 0; 
}; 

base.cpp:

#include "base.h" 
base::base() {} 
base::~base() {} 

main.cpp:

#include "base.h" 
#include <dlfcn.h> 
#include <iostream> 

int main() { 
    void* handle = dlopen("liblib.so", RTLD_NOW); 
    if(handle == NULL) std::cout << dlerror() << std::endl; 

    // dlsym, ... 
} 

lib. cpp:

class derived : public base { 
public: 
    derived() {} 
    virtual ~derived() {} 
    virtual int value() { return 42; } 
}; 

extern "C" derived* create_object() { 
    return new derived(); 
} 

To kompiluje dobrze z:

g++ -shared -fPIC lib.cpp -o liblib.so 
g++ base.cpp main.cpp -ldl -o app 

Na starcie jednak wywala go z powodu brakującego typeinfo symbol

liblib.so: undefined symbol: _ZTI4base 

w poprzednich pytań znalazłem tutaj, błąd ten był zwykle spowodowane albo brakujące "= 0;" lub brakującą definicję funkcji wirtualnej. Jednak w powyższym przykładzie wartość base :: value jest czysto wirtualna, a destruktor ma definicję. Dziwo nm donosi _ZTI4base jak zdefiniowana w aplikacji:

$ nm app | grep _ZTI4base 
0000000000601050 V _ZTI4base 

Więc dlaczego nie jest łącznik przy użyciu tej definicji?

Jedynym sposobem, jaki znalazłem do tej pory, aby uzyskać działający kod, jest implementacja konstruktora i destruktora w pliku nagłówkowym. Po wykonaniu tej czynności odpowiednie symbole dla zasady są zgłaszane w bibliotece llsb.so przez nm i całkowicie znikają z aplikacji, co prawdopodobnie oznacza, że ​​ich definicje zostały wkompilowane do biblioteki, a nie do aplikacji, co nie jest tym, co chciałem osiągnąć. Czy ktoś ma pomysł, jak uzyskać powyższe działa bez robienia tego?

+1

Daj '--demangle' na' nm', aby zobaczyć demangled nazwę funkcji. – Shahbaz

Odpowiedz

2

Potrzebujesz opcji -rdynamic podczas łączenia programu, aby wyeksportować jego symbole i udostępnić je bibliotekom załadowanym dlopen().

Powiązane problemy