Posted tagged ‘shared object’

Criando bibliotecas dinâmicas em C

outubro 17, 2008

Muitas vezes temos a necessidade de incluir bibliotecas dinâmicas de terceiros em nossos programas. Este já é um processo consideravelmente comum para quem desenvolve software.

Porém algumas vezes, precisamos ou desejamos ser os produtores destas bibliotecas, para que outros possam utilizar nossas bibliotecas, ou mesmo para “modularizar” ou “desacoplar” parte do código do executável principal.

Desacoplar parte do software é algo desejável, tendo em vista que pode-se modificar o tratamento de funções dentro de uma biblioteca dinâmica, deste que não modifique-se a interface, sem a necessidade de recompilação do executável principal.

Grandes projetos, tendem a possuir várias bibliotecas dinâmicas, facilitando o desenvolvimento por grupos de programadores em paralelo, acelerando o processo como um todo.

Também é possível a carga da biblioteca dinâmica em tempo de execução do programa através da “libdl”, porém, isto fica para um próximo post.

Linkando uma biblioteca em um programa qualquer:

samuel@samuel ~/testes/c $ gcc main.c -o main -lpthread

O que acontece, é que quando passamos o parâmetro “-l<biblioteca>” para o “linker”, o mesmo, procura nos diretórios padrões do sistema, por um arquivo chamado “lib<biblioteca>.so.<versao>”, carregando ele na inicialização do programa.

Estas bibliotecas, tem de ser carregadas de algum local no sistema de arquivos. Este local, geralmente é “/lib”, “/usr/lib” ou “/usr/local/lib”, de acordo com os padrões definidos pela GNU.

Adicionando caminhos de busca a bibliotecas:

Também é possível adicionar locais a serem buscadas as bibliotecas, possibilitando o carregamento de bibliotecas que estejam fora dos caminhos padrões.

Existe o arquivo “/etc/ld.so.conf” que contém uma lista de diretórios extras com “shared objets”, o qual pode ser editado, informando-se novos caminhos.

Após a edição deste arquivo, é necessário recarregar o “cache” de bibliotecas, o que pode ser feito através da execução do programa “ldconfig”.

Outra forma de adicionar caminhos para “shared objects” é através da variável de ambiente “LD_LIBRARY_PATH”, que pode conter um lista de diretórios separados por vírgula. Geralmente, a alteração desta variável de ambiente se dá apenas em tempo de desenvolvimento.

Criando uma biblioteca dinâmica

Código “simple.c”:

#include <stdio.h>

void show_hello(void) {
	printf("Hello World!!!");
}

Compilando como uma “shared object”:

samuel@samuel ~/testes/c $ gcc -fPIC -shared -g simple.c -o simple.so

Opções passadas para o GCC:

-fPIC: Faz com que se gere um biblioteca com código “Position-Independent”. Ou seja, o código objeto gerado pode ser posicionado em qualquer área de memória de um programa que venha a incluir esta biblioteca.

-shared: Indica que deve-se gerar um “shared object”.

-g: Habilita informações de depuração. Fazendo com que seja possível utilizar um debugger para facilitar a detecção de erros.

Código “main.c”:

int main() {
	show_hello();
}

Compilando com a “shared object”:

samuel@samuel ~/testes/c $ gcc -o main main.c ./simple.so

Desta forma, a biblioteca “simple.so” vai ficar ligada através do seu caminho relativo (./simple.so), que neste caso, é o mesmo diretório, não sendo necessário a alteração dos caminhos de busca das bibliotecas dinâmicas.

Visualizando as dependências de um programa

Para exibir uma lista das bibliotecas dinâmicas que um programa precisa, basta utilizar o utilitário “ldd”.

samuel@samuel ~/testes/c $ ldd main
     linux-gate.so.1 =>  (0xb7fa1000)
     ./simple.so (0xb7f9e000)
     libc.so.6 => /lib/libc.so.6 (0xb7e55000)
     /lib/ld-linux.so.2 (0xb7fa2000)

É claro que há muito mais a falar sobre bibliotecas dinâmicas. Pretendo voltar a escrever mais sobre isto em breve.