Biblioteca compartilhada dinâmica de C ++ no Linux

Esta é uma continuação da compilation da Dynamic Shared Library com g ++ .

Eu estou tentando criar uma biblioteca de classs compartilhadas em C ++ no Linux. Eu sou capaz de obter a biblioteca para compilar, e eu posso chamar algumas das funções (não-class) usando os tutoriais que eu encontrei aqui e aqui . Meus problemas começam quando tento usar as classs definidas na biblioteca. O segundo tutorial ao qual eu me associei mostra como carregar os símbolos para criar objects das classs definidas na biblioteca, mas deixa de usar esses objects para executar qualquer trabalho.

Alguém sabe de um tutorial mais completo para criar bibliotecas de classs C ++ compartilhadas que também mostra como usar essas classs em um executável separado? Um tutorial muito simples que mostra a criação de objects, use (getters e setters simples ficariam bem), e a deleção seria fantástica. Um link ou uma referência a algum código-fonte aberto que ilustre o uso de uma biblioteca de classs compartilhada seria igualmente bom.


Embora as respostas de codelogic e nimrodm funcionem, eu só queria acrescentar que peguei uma cópia do Beginning Linux Programming desde que fizesse essa pergunta, e seu primeiro capítulo tem código C de exemplo e boas explicações para criar e usar bibliotecas estáticas e compartilhadas . Esses exemplos estão disponíveis na Pesquisa de Livros do Google em uma edição mais antiga desse livro .

   

myclass.h

#ifndef __MYCLASS_H__ #define __MYCLASS_H__ class MyClass { public: MyClass(); /* use virtual otherwise linker will try to perform static linkage */ virtual void DoSomething(); private: int x; }; #endif 

myclass.cc

 #include "myclass.h" #include  using namespace std; extern "C" MyClass* create_object() { return new MyClass; } extern "C" void destroy_object( MyClass* object ) { delete object; } MyClass::MyClass() { x = 20; } void MyClass::DoSomething() { cout<  

class_user.cc

 #include  #include  #include "myclass.h" using namespace std; int main(int argc, char **argv) { /* on Linux, use "./myclass.so" */ void* handle = dlopen("myclass.so", RTLD_LAZY); MyClass* (*create)(); void (*destroy)(MyClass*); create = (MyClass* (*)())dlsym(handle, "create_object"); destroy = (void (*)(MyClass*))dlsym(handle, "destroy_object"); MyClass* myClass = (MyClass*)create(); myClass->DoSomething(); destroy( myClass ); } 

No Mac OS X, compile com:

 g++ -dynamiclib -flat_namespace myclass.cc -o myclass.so g++ class_user.cc -o class_user 

No Linux, compile com:

 g++ -fPIC -shared myclass.cc -o myclass.so g++ class_user.cc -ldl -o class_user 

Se fosse por um sistema de plugins, você usaria MyClass como uma class base e definiria todas as funções necessárias virtuais. O autor do plug-in derivaria do MyClass, replaceia os create_object e implementaria o create_object e destroy_object . Seu aplicativo principal não precisaria ser alterado de forma alguma.

A seguir, é mostrado um exemplo de uma biblioteca de classs compartilhada [h, cpp] e um módulo main.cpp que usam a biblioteca. É um exemplo muito simples e o makefile pode ser muito melhor. Mas funciona e pode ajudá-lo:

shared.h define a class:

 class myclass { int myx; public: myclass() { myx=0; } void setx(int newx); int getx(); }; 

shared.cpp define as funções getx / setx:

 #include "shared.h" void myclass::setx(int newx) { myx = newx; } int myclass::getx() { return myx; } 

main.cpp usa a class,

 #include  #include "shared.h" using namespace std; int main(int argc, char *argv[]) { myclass m; cout < < m.getx() << endl; m.setx(10); cout << m.getx() << endl; } 

e o makefile que gera libshared.so e liga main com a biblioteca compartilhada:

 main: libshared.so main.o $(CXX) -o main main.o -L. -lshared libshared.so: shared.cpp $(CXX) -fPIC -c shared.cpp -o shared.o $(CXX) -shared -Wl,-soname,libshared.so -o libshared.so shared.o clean: $rm *.o *.so 

Para executar de verdade 'main' e link com libshared.so você provavelmente precisará especificar o caminho de carregamento (ou colocá-lo em / usr / local / lib ou similar).

O seguinte especifica o diretório atual como o caminho de pesquisa para bibliotecas e executa main (syntax bash):

 export LD_LIBRARY_PATH=. ./main 

Para ver que o programa está vinculado ao libshared.so você pode tentar o ldd:

 LD_LIBRARY_PATH=. ldd main 

Imprime na minha máquina:

  ~/prj/test/shared$ LD_LIBRARY_PATH=. ldd main linux-gate.so.1 => (0xb7f88000) libshared.so => ./libshared.so (0xb7f85000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e74000) libm.so.6 => /lib/libm.so.6 (0xb7e4e000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7e41000) libc.so.6 => /lib/libc.so.6 (0xb7cfa000) /lib/ld-linux.so.2 (0xb7f89000) 

Basicamente, você deve include o arquivo de header da class no código em que deseja usar a class na biblioteca compartilhada. Em seguida, quando você vincular, use o sinalizador ‘-l’ para vincular seu código à biblioteca compartilhada. Claro, isso requer o .so estar onde o sistema operacional pode encontrá-lo. Veja 3.5. Instalando e usando uma biblioteca compartilhada

Usar o dlsym é para quando você não sabe em tempo de compilation qual biblioteca você quer usar. Isso não parece ser o caso aqui. Talvez a confusão é que o Windows chama as bibliotecas carregadas dinamicamente se você faz a vinculação em compilation ou em tempo de execução (com methods análogos)? Se sim, então você pode pensar em dlsym como o equivalente a LoadLibrary.

Se você realmente precisa carregar dinamicamente as bibliotecas (ou seja, eles são plug-ins), então esta FAQ deve ajudar.