Si ya revisaste el post anterior sobre construcción de bibliotecas podremos proseguir con el hecho de
que ya tenemos algunos conceptos básicos de nuestro lado, esta vez
relizaremos el mismo ejemplo lo que cambia es las herramientas.
Primero construiremos la lib estática, después compartida y por
último de ejecución (que no es más que la misma biblioteca
compartida lo que se carga en tiempo de ejecución).
Libtool:
Según
su propia documentación (apt-get install libtool-doc) fue diseñado
desde sus inicios para soportar un número arbitrario de tipos de
bibliotecas, más tarde se ha ido portando a otras plataformas y
gradualmente se han ido desarrollando nuevos paradigmas que describen
la relación entre las bibliotecas y los programas.
Consideremos el sigiente código con el
cual crearemos la biblioteca estática y compartida:
//module.c
float mult (float fac1, float fac2)
{
return fac1 * fac2;
}
Biblioteca estática:
1. Creamos un directorio donde
“instalaremos” la lib.
mkdir -p /tmp/install
2. Compiamos el código.
libtool --verbose --mode=compile gcc
-g -O -c module.c -static
3. Enlazamos el código, si no ponemos
-rpath /tmp/install al comando anterior tendremos que ejecutar
libtool --finish /usr/local/lib después
para que se complete la instalación correctamente.
libtool --verbose --mode=link gcc
-module -o module.la module.lo -rpath /tmp/install -static
4. Instalamos
libtool --mode=install install
module.la /tmp/install
Ya tenemos lista la lib en /tmp/install
que puedes usar como en el post anteriorque mencionaba al inicio y
además notar que se encuentra en el direcorio oculto (ls .libs/).
Biblioteca dinámica:
Recomendable eliminar los archivos
anteriores para ver el nuevo resultado y repitiendo los pasos para
este caso tenemos:
1. mkdir -p /tmp/install
2. libtool --verbose --mode=compile gcc
-g -O -c module.c -shared
3. libtool --verbose --mode=link gcc
-module -o module.la module.lo -rpath /tmp/install -shared
4. libtool --mode=install install
module.la /tmp/install
Biblioteca de
ejecución:
Para ver como usamos una lib en tiempo
de ejecución usaremos el siguiente código:
#include <stdio.h>
#include <ltdl.h>
#include <stdlib.h>
//declaramos una variable(puntero a la función así que
//debe coincidir en los tipos)
float (*mult)(float fac1, float fac2);
int main (int argc, char *argv[])
{
lt_dlhandle handle;
lt_dlinit ();
lt_dladdsearchdir ("./");
handle=lt_dlopenext ("module");
if (!handle)
{
printf ("Error, módulo no cargado: %s\n",
lt_dlerror());
exit (EXIT_FAILURE);
}
const lt_dlinfo *info;
info = lt_dlgetinfo (handle);
if (!info)
{
fprintf (stderr, "No se pudo obtener la información del módulo: %s\n", lt_dlerror());
lt_dlclose (handle);
exit (EXIT_FAILURE);
}
if (info->name)
{
printf ("Nombre del módulo: %s\n", info->name);
}
else
{
printf ("No es un módulo libtool\n");
}
//casteo al tipo de la función
mult = (float(*)(float, float))lt_dlsym(handle, "mult");
if (mult)
{
printf ("Resultado desde el módulo: %f\n", mult(5.0, 10.0));
}
else
{
perror ("No se pudo cargar la función\n");
lt_dlclose (handle);
exit (EXIT_FAILURE);
}
lt_dlclose (handle);
return 0;
}
Recomendable eliminar los archivos
anteriores para ver el nuevo resultado y repitiendo los pasos para
este caso tenemos:
1. libtool --verbose --mode=compile gcc
-g -O -c module.c -shared
2. libtool --verbose --mode=link gcc
-module -o module.la module.lo -rpath /tmp/install -shared
3. libtool --mode=link gcc
-export-dynamic -o programdl program.c -lltdl
Un detalle importante es notar que la
lib se contruye de la misma manera que la compartida, el programa es
el que se contruye de forma diferente a la convencional y además con
ldd como en el post anterior puedes ver como program no depende de
module por lo que los pasos 2 y 3 se pueden cambiar de orden ya que
program no necesita saber nada acerca de module en tiempo de
compilación.
NOTA: Para tener más referencia
consulte man libtool o /usr-sha-doc-libtool-doc.