Estou criando uma ferramenta que carrega bibliotecas dinâmicas. No Windows o carregamento das bibliotecas dinâmicas (as dll) inclui o diretório atual (ou pasta corrente). No Linux não, o carregamento ocorre somente nos caminhos padrão do sistema. Há uma variável de ambiente que ajuda nisso, a LD_LIBRARY_PATH
. Porém seu uso pode ser inconveniente por algumas razões, vou citar três:
LD_LIBRARY_PATH
, o que afeta todo o sistema trazendo o risco de bibliotecas com código malicioso; LD_LIBRARY_PATH
, que se tiver uma lista extensa ou locais na rede pode levar a uma situação caótica; A lista de problemas poderia ser bem mais extensa, mas vamos nos ater ao meu caso. A ferramenta tem por objetivo simplificar as coisas, e precisar configurar uma variável de ambiente previamente não facilita em nada. A solução seria a própria ferramenta definir a variável de ambiente e carregar as bibliotecas. Mas esta é outra coisa que não funciona. O sistema verifica a LD_LIBRARY_PATH
uma vez ao iniciar o programa e modificar a variável de ambiente não mudará nada a partir dai.
Mas relaxe, porque tem solução. Modificar a variável de ambiente, reiniciar o programa e carregar a biblioteca com dlopen
. Vamos para a prática:
libhello.c:
#include <stdio.h>
void hello() {
printf("Hello World!\n");
}
Para compilar: gcc -shared -fPIC libhello.c -o libhello.so
hello.c:
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef void (*type_hello)();
int main(int argc, char *argv[]) {
char *s = getenv("LD_LIBRARY_PATH");
if (s != NULL && strcmp(s, ".") != 0) {
setenv("LD_LIBRARY_PATH", ".", 1);
execv(argv[0], argv);
}
void *lib = dlopen("./libhello.so", RTLD_NOW);
if (lib == NULL) return 1;
type_hello hello = (type_hello)dlsym(lib, "hello");
if (hello != NULL) hello();
dlclose(lib);
return 0;
}
Para compilar: gcc -o hello hello.c -ldl
Um exemplo também com Free Pascal:
hello.pas:
uses dynlibs;
type
thello = procedure;
var
hello: pointer;
handle: thandle = 0;
function execv(const path: pchar; const argv: ppchar): integer; cdecl; external;
function getenv(const name: pchar): pchar; cdecl; external;
function setenv(const name, value: pchar; overwrite: boolean): integer; cdecl; external;
begin
if getenv('LD_LIBRARY_PATH') <> '.' then
begin
setenv('LD_LIBRARY_PATH', '.', true);
execv(argv[0], argv);
end;
handle := loadlibrary('./libhello.so');
if handle = 0 then halt(1);
hello := getprocaddress(handle, 'hello');
if hello <> nil then thello(hello)();
freelibrary(handle);
end.
Para compilar: fpc hello
E enfim, é isso. Para saber mais sobre: LD_LIBRARY_PATH.
br_lemes, o Elfo insano (Múltipla Personalidade)
Theme by Breno Ramalho Lemes under Creative Commons Attribution, based on Jekyll Clean by Scott Emmons and icons by FatCow.