Bibliotecas compartidas de C++ en Linux
A veces, varios programas necesitan hacer las mismas cosas, como E/S por ejemplo. Hace ya bastante tiempo se desarrolló el concepto de biblioteca (o librería) para adaptar esto. Las funciones se colocan en un archivo, y luego, cada vez que se crea un programa, este extrae de la biblioteca las funciones que necesita.
En su momento, esto fue un gran avance, pero tenía varias desventajas. Los ejecutables se hacen más grandes ya que cada uno de ellos incrusta código copiado de las bibliotecas. Si se encuentra un error en la biblioteca o se agrega una característica, el ejecutable no hace uso de ella a menos que se vuelva a crear.
La solución a esto son las bibliotecas compartidas (o librerías dinámicas). El mecanismo de las bibliotecas compartidas esta fuera del alcance de este artículo. Solo veremos como crearlas y utilizarlas.
Regresemos al programa del dado que hicimos en C. Este programa tiene dos archivos fuente. Supongamos que nuestra función tirarDado (del archivo tirador.c) nos es muy útil, no solo en nuestro programa, sino en muchos otros programas que utilicen dados. Podemos pensar entonces en colocar dicha función en una biblioteca para que otros programas puedan usarla.
Primero necesitamos crear la biblioteca compartida. Para ello compilamos el archivo que contiene la función así:
gcc -fPIC -c tirador.c
Ahora lo convertimos en una biblioteca compartida llamada libtirar.so.1.0:
gcc -shared -Wl,-soname,libtirar.so.1 -o libtirar.so.1.0 tirador.o
Por último crearemos un enlace para libtirar.so, para que el programa en ejecución no necesite mantener un registro de la información de versión en el nombre de la biblioteca compartida:
ln -s libtirar.so.1.0 libtirar.so.1
ln -s libtirar.so.1 libtirar.so
Ahora que tenemos la biblioteca, debemos crear el programa principal para que enlace con esa biblioteca en tiempo de ejecución, en lugar de incluir el código dentro del ejecutable:
gcc -o juego juego.c -L. -ltirar
La opción -L. le indica al compilador que busque bibliotecas en el directorio actual, y la opción -ltirar le indica que busque una biblioteca llamada libtirar.so.
Al ejecutar el programa, el sistema operativo cargará dinámicamente la biblioteca correcta, pero tiene que saber donde buscarla. Si la biblioteca no se encuentra en un lugar estándar (/usr/lib por ejemplo), puede asignar una variable de entorno para que le indique en dónde localizar bibliotecas adicionales:
export LD_LIBRARY_PATH=/home/usuario/mislibrerias
Por último, para ver qué librerías usa un programa, utilice el comando ldd:
ldd juego
libtirar.so.1 =>/mnt/hda1/home/casidiablo/juegolibrerias/libtirar.so.1 (0×40018000)
libc.so.6 => /lib/libc.so.6 (0×40029000)
/lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0×40000000)
Otro ejemplo de bibliotecas… crear una biblioteca estática
A diferencia de las bibliotecas compartidas, al momento de compilar bibliotecas estáticas, se incluyen en el programa las rutinas que utiliza de la biblioteca; en otras palabras las rutinas están insertas en el programa sin la posibilidad de ser utilizados por otro programa. Nuestra demostración se basará en la construcción de una biblioteca estática; dentro de nuestra biblioteca incluiremos un procedimiento que imprimirá un mensaje en pantalla el que será pasado por parámetro y una función que nos entrega en cálculo del factorial de un numero dado (pasado por parámetro); para que luego estas rutinas sean llamadas desde un programa de ejemplo.
El proceso para crear bibliotecas estáticas es escribir el código fuente, compilar a código objeto el fuente y crear la biblioteca con los archivos objetos. A continuación procederemos a escribir nuestras rutinas que serán incluidas en la biblioteca, los archivo de las rutinas serán factorial.c e imprimir.c
//imprimir.c
#include<stdio.h>
void imprimir_en_pantalla(const char* mensaje)
{
printf("%s",mensaje);
}
//factorial.c
#include<stdio.h>
long factorial(long numero)
{
if(numero>0)
return numero * factorial(numero-1);
else return 1;
}
Ahora compilaremos estos archivos fuente y los convertiremos en código objeto utilizando gcc:
gcc -c imprimir.c factorial.c
Esto creará los archivos objeto (imprimir.o y factorial.o). El siguiente paso será crear nuestra biblioteca estática con estos archivos de código objeto; a la biblioteca la llamaremos libejemploestatica.a:
ar rsc libejemploestatica.a imprimir.o factorial.o
El comando ar creará nuestra biblioteca (opcion c), introducirá los archivos objeto al archivo creado (opción r) y por último creará un índice de los módulos (opción s), esto último permite que el linker (ld) al momento de compilar (ld es llamado por gcc) no tenga que leerse toda la biblioteca completa ya que se agregan los índices y descripción de los módulos. El proceso de crear el índice de los módulos también se pude realizar con ranlib.
//miprograma.c
#include<stdio.h>
#include "libejemploestatica.h"
int main()
{
printf("Programa de ejemplo de utilizacion de biblioteca\n");
imprimir_en_pantalla("Vamos a calcular un factorial\n");
printf("El valor del factorial de 4 es: %i\n",factorial(4));
}
Ahora nos falta crear nuestro archivo de cabecera (header), que son los que tienen terminación .h, en este archivo se incluirán las llamadas a las rutinas de la biblioteca y es una manera elegante porque también puedes incluir estas llamadas en el programa que las vas utilizar. El archivo de cabecera libejemploestatica.h tendrá el siguiente contenido:
extern void imprimir_en_pantalla(const char*); extern long fatorial(long);
No es necesario que el archivo de cabecera y biblioteca sean iguales antes de la extensión. Ahora crearemos el archivo ejecutable en base a nuestro programa principal (miprograma.c), el cual utilizará la biblioteca que hemos creado. Para ello debemos compilarlo utilizando la biblioteca:
gcc -o programa_ejecutable miprograma.c -L. -lejemploestatica
Con la opción -L indicamos donde se encuentra nuestro archivo de cabecera, como en este se encuentra en el mismo directorio utilizamos el punto (-L.). Con la opción -l indicamos el nombre de la librería. Fíjate que no es necesario colocar el nombre completo (libejemploestatica) ya que gcc asume que los nombre de bibliotecas empiezan con el prefijo “lib”. Ahora ya tendremos el archivo ejecutable listo para correr nuestro programa:
$ ./programa_ejecutable
Programa de ejemplo de utilizacion de biblioteca
Vamos a calcular un factorial
El valor del factorial de 4 es: 24
14 Comentarios | deja el tuyo





gracias por este articulo en verdad es muy bueno,,, y me saco de mas de un problema en la universidad… muchas gracias
Me alegra bastante que te hayan servido… para eso están.
Un saludo!
Muy útil, una forma sencilla entre diferenciar entre los dos tipos de bibliotecas
Esto me parece muy bueno, pero tengo una duda, yo trabajo con el Qt Creator y me haria falta usar mi libreria dinamica como uso por ejemplo #include , como podria usar de igual manera mi libreria., ejemplo #include
Espero respuesta.
Saludos.
mi problema es que copio la libreria para /usr/lib y el header /usr/include
y en el Qt Creator incluyo la libreria y me completa codigo y todo pero me da el siguiente error undefined reference to ‘suma(int, int)’, es como si no encontrara la implementacion de esos metodos, que pudiera ser?
hola de nuevo se pueden manejar graficos en c++ en fedora 10?
Umm… nunca he manejado gráficos en C++, pero aquí lo importante es que es C++, y que funciona en cualquier Linux.
Un saludo.
perdon una pregunta, esque cuando ejecuto el programa que he hecho (exe en mi caso asi lo nombre) cuando me pide las entradas todo bien, pero cuando casi esta por terminar me diice VIOLACION DE SEGMENTO, el codigo es:
#include
#include
int main(){
int a,b,c;
printf(“Introduzca A \n”);
scanf(“%d”,a);
printf(“Introduce B \n”);
scanf(“%d”,b);
c=(a*b);
printf(“%d es el producto “,c);
return 0;
}
hasta el punto de printf que pide introducir B lo ejecuta bien, pero luego viene el error que comente, porfavor cualquier ayuda le agradeceria
perdon una pregunta, esque cuando ejecuto el programa que he hecho (exe en mi caso asi lo nombre) cuando me pide las entradas todo bien, pero cuando casi esta por terminar me diice VIOLACION DE SEGMENTO, el codigo es:
#include “stdio.h”
#include “stdlib.h”
int main(){
int a,b,c;
printf(“Introduzca A \n”);
scanf(“%d”,a);
printf(“Introduce B \n”);
scanf(“%d”,b);
c=(a*b);
printf(“%d es el producto “,c);
return 0;
}
hasta el punto de printf que pide introducir B lo ejecuta bien, pero luego viene el error que comente, porfavor cualquier ayuda le agradeceria
Pruébalo así:
#include “stdio.h”
#include “stdlib.h”
int main(){
int a,b,c;
printf(“Introduzca A \n”);
scanf(“%d”,&a);
printf(“Introduce B \n”);
scanf(“%d”,&b);
c=(a*b);
printf(“%d es el producto “,c);
return 0;
}
Gracias por tu ayuda Cristian, ahora si me funciona
Muchas Gracias
Hola.
¡Excelente artículo!. ¿Podrías explicar un poco más porque se deben crear enlaces directos a la librería?.
Gracias
gracias es cool pero serias taan amable de poner mas ++++ cosas narralo y explica lo q contiene pero bueno es cool *
* me gusta * * * *
* es genial ** * * * ** * * * * *************************************************************************************************************************************************************** *** **
* me sirvia