Biblotecas Estaticas y Dinamicas en C
Software
Cuando las aplicaciones adquieren un tamaño decente y necesitamos compartir y estandarizar formas de hacer las cosas, es necesario crear bibliotecas.
Esta bibliotecas pueden ser vistas como un conjunto de funciones o subrutinas, que pueden ser incrustadas o llamadas en el codigo de los programas que escribimos. Una buena Biblioteca es además óptima y bien documentada.
Para fines practicos nos interesan 2 tipos de bibliotecas:
- Bibliotecas Estáticas: Estas bibliotecas son incluidas directamente en el código objeto del ejecutable en tiempo de compilación, Tienen la desventaja de que el ejecutable sea demasiado grande y que si se tienen varios programas que usen esa biblioteca, esa misma biblioteca esta cargada (repetida) varias veces en memoria. sin embargo tiene la ventaja de que el programa ejecutable puede correr sin necesidad de sistema operativo, por ejemplo, cargandolo en memoria usando grub =).
- Bibliotecas Dinámicas: Son llamadas y enlazadas dinámicamente en tiempo de ejecución, es decir existe solo una copia de la biblioteca en memoria que es usada por todos los programas que la requieran, la desventaja es que requiere de un SO para ser cargada y enlazada.
En C y usando el compilador gcc, todas las bibliotecas (salvo las estandar) deben ser ligadas con la opcion -l si estan en la ruta estándar o -L si hay que especificar el path de la biblioteca. La opción -I es util cuando se desea cambiar la trayectoria de búsqueda de los archivos especificados en #include.
Imaginemos siguiente codigo en C en los archivos libgss.h, gss.c y random.c respectivamente:
-----------------------------------------------libgss.h---------------------------------------------
//archivo libgss.h
extern int gss(void);
extern int random(void);
--------------------------------------------------gss.c----------------------------------------------
/*GetSecureSeed: pequenia funcion que regresa un entero Pseudo-aleatorio para ser usado como inicializador en la funcion srand()
de la biblioteca estandar*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define RDNFIL "/dev/random"
#define INTBUF 4
int gss(void){
int fd,ret;
fd=open(RDNFIL,O_RDONLY);
read(fd,&ret,INTBUF);
close(fd);
return ret;
}
//disculpen la suciedad de este codigo, solo funciona en arquitecturas donde los enteros sean de 4 bytes (32bits) ,
//pero solo es un ejemplo, no sean duros conmigo
---------------------------------------------------random.c------------------------------------------------
/*lo vi una vez en una tira y ocupaba otra funcion para el ejemplo =P*/
int random(void){
return 4;
}
Haciendo Bibliotecas Estaticas.
Para la creacion de bibliotecas estaticas nos auxiliamos de ar, ranlib y gcc.
Primero: compilacion, esto nos entregara 2 archivos, "gss.o" y "random.o"
gcc -c gss.c random.c
Segundo: crear biblioteca, una biblioteca con el nombre "libgss.a", la terminacion '.a' es estandar en las bibliotecas estaticas de UNIX(R)
ar r libgss.a gss.o random.o
Tercero: indexando para el cargador
ranlib libgss.a
Haciendo Bibliotecas Dinamicas
Primero: compilar con opciones de facil relocalizacion (PIC:Position Independent Code)
gcc -c -fPIC gss.c random.c
Segundo: Crear la biblioteca compartida, la terminacion ".so" es estandar en los UNIX(R)
gcc -shared -o libgss.so gss.o random.o
Probando y agregando un poco elegancia
Necesitamos un pequeño programa para probar las bibliotecas, algo tan sencillo como imprimir los numeros que regresan las funciones:
--------------------test.c---------------------------
#include <stdio.h>
#include "libgss.h"
int main(){
int a,b,c;
a=gss();
srand(a);
b=rand();
c=random();
printf("gss:%d\nrand:%d\nrandom:%d\n",a,b,c);
return 0;
}
------------------------------------------------------
Este programa se compilaria de la siguiente manera:
gcc -I./ -L./ -o test test.c -lgss
Con -I indicamos el path de los "headers" y con -L el de las bibliotecas. La opcion -l indica la biblioteca que "Cargara". Usualmente no se escribe completa, salvo que se quiera especificar alguna biblioteca (libgss.a para estatica o libgss.so para dinamica), por defecto cargara la biblioteca dinamica y es un estandar que la bibliotecas empienzen con "lib", entonces este se omite.
Ahora, agregando un poco de elegancia, crearemos un par de directorios, uno lib y el otro include. moveremos las bibliotecas a lib y el hader a include. Esto deberia hacerse siempre
mkdir lib include
mv libgss.[!cho]? lib/
mv libgss.h include/
gcc -I./include -L./lib -o test test.c -lgss
¿Deseas saber mas?
- man ar
- man ranlib
- man gcc
Permalink: http://mononeurona.org/entries/view/vendaval/1769
Comentblogs:









