Consultas, desarrollo de programas y petición de presupuestos:

jueves, 12 de julio de 2012

librerias en C (II): Como se crean y se usan

Descargamos  este archivo, y nos encotramos estos 4 archivos:
programa que usa la librería: pru_lib_argumentos.c

makefile: genera la librería

liberia en si: argumentos.c y argumentos.h


Abrimos el programa: pru_lib_argumentos.c

Vemos la linea:
#include "argumentos.h"

//que hace que busque el archivo .h en el mismo directorio donde este el programa, tambien podiamos indicar un directorio. #include “/home/uno/argumentos.h”

struct argumentos *resul; // esta estructura esta definica en la librería “argumentos.h”

resul = procesarArgumentos("abcdef", argc, argv); //la funcion procesarArgumentos() le pasamos los valores que son validos “abcdef”, y los argc y argv, que hemos recibido de argumentos en el pograma “pru_lib_argumentos.c” y la funcion nos devuelve la estructura resul rellena.

for(c = 0; c < resul->ar_cantNoArgs; c++) // hace for hasta la cantidad de no argumentos (que no empiezan el argumento por “-”, directorio, ficheros o errores de escritura)

El programa nos muestra, los distintos valores y el argumento que usamos.


Pasamos al fichero: argumentos.h

Siempre que creamos una librería, necesitamos tener un fichero de encabezado (.h), que nos va a indicar os prototipos del contenido de la librería: funciones, estructuras,etc

Como vemos en la primera linea “#ifndef _ARGUMENTOS_H” (la ponemos asi para que no este definida en ningun sitio ni por causalidad).
Y su traduccion: “si no esta definido _ARGUMENTOS_H”
A continuación la defino:
#define _ARGUMENTOS_H, (para que no se vuelva a definirla, y asi nos evitamos un error al intentar incluir varias veces la misma libreria), incluyo las cabeceras que me hacen faltan en la librería.

Si estuviese ya definido, se va al final “#endif

char *arg_args: puntero a tabla de caracteres (ejemplo: “abcde”)

char **ar_noArgs: puntero a puntero: tabla de 2 dimensiones, una lista de palabras (ejemplo: “fichero1”, “fichero2”,”fichero3”)


De la linea 21 a la 24, se declaran las funciones:
struct argumentos *procesarArgumentos(char *,int, char **); // develve puntero a una estructura argumentos y le pasamos una cadena, un numero, y una lista de cadenas.

int argumento(char *,char *);// devuelve un entero, y le ha pasado 2 cadenas de caracteres.

int esArgumento(char *);// devuelve un entero, y le ha pasado 1 cadena de caracteres.

int cantidadArgumentos(int, char **);// devuelve un entero, y le ha pasado un entero y una lista de cadenas de caracteres.


Abrimos el archivo “argumentos.c”:

Es donde esta el código fuente: las descripciones de las funciones.

En la linea 3, le tenemos que poner:
#include "argumentos.h" // estas obligado a ponerlo ya que alli se definen las funciones y las estructuras que vamos a usar.



ar = malloc(sizeof(struct argumentos)); // asigno espacio de memoria a la variable ar
ar->ar_args = malloc(sizeof(char)); // sizeof(char): reservo espacio para un solo carácter, por que aunque “abcde” , ademas hay que añadirle “\0”, anque no haya argumento.

Le doy valores iniciales a la estructura
ar->ar_cantArgs = 0;
ar->ar_cantNoArgs = 0;
ar->ar_cantNoValidos = 0;
ar->ar_cantValidos = 0;
*(ar->ar_args) = '\0';
*(ar->ar_noArgs) = '\0';
*(ar->ar_noValidos) = '\0';
*(ar->ar_validos) = '\0';

Linea 133: definicion de la funcion
esArgumento(): devuelve si es un argumento (empieza por “-”) 1, y si no devuelve 0


Linea 54:
while (*argu) // se repite mientras halla letras, (hasta que llegue “\0”)

Linea 57: si valor>0, es un argumento valido (valor = argumento(valen, argu);)

Linea 64:
tama = strlen(ar->ar_args); // devuelve el tamaño de la cadena ar->arg_args
ar->ar_args = realloc(ar->ar_args, sizeof(char) * (tama + 1)); // la funcion realloc: es similar a malloc, pero amplia el tamaño de la memoria asignada, pero reservando el contenido. “REDIMENSIONA”

Recibe 2 argumentos:
1º. El puntero al que que tiene que reasignar memoria
2º. El tamaño que asigna. (sizeof(char) * (tama + 1))



Nota:
REALLOC: amplia porque le digo tama+1, tambien se puede quitar!! (tama-1)


Linea 76:
suma += valor; // es igual suma=suma+valor

Linea 104: aumento de tabla de 2 dimensiones:
ar->ar_noArgs = realloc(ar->ar_noArgs, sizeof(char) * (tama + 1)); // aumento el sitio del puntero
ar->ar_noArgs[tama] = (char *) malloc(sizeof(char) * (strlen(argu) + 1));
strcpy(ar->ar_noArgs[tama],argv[c]);

Ver esquema siguiente:

Si nos vamos a construir el programa, y nos da el siguiente error:
Nos vamos al directorio donde ese el programa y la librería, y le ponemos la orden: make
que busca un archivo llamado makefile, y hace lo que ponga ese archivo.
En este archivo makefile, hace que se construya una librería dinamica y estatica, y compila el programa pru_lib_argumentos, creado 3 archivos:
pru_lib_argumentos_dina
pru_lib_argumentos_esta
libargumentos.so


Explicación lo que hace makefile:
linea:
cc -Wall -I. -I/home/julio/include -L. -L/home/julio/lib -c -o pru_lib_argumentos.o pru_lib_argumentos.c

cc: es compilador de c (gcc es un compilardor de c,c++, java, fortran, etc)

-Wall: que nos de los avisos
-I: indicamos el nombre de los escritorios donde debe buscar los ficheros .h
-L: directorios donde debe de buscar librerias.
-c: indica que solo quiero compilar, no enlazar con la libreria
-o: indica el nombre que quiero darle a mi programa
y luego le digo el nombre de mi programa fuente “pru_lib_argumento.c”

Y luego le siguen 3 bloque de gcc

Tipos de librerias:
Las librerias son un grupo de funciones pero sin el main. Al compilarlo se le dice que sea estatica o dinamica.
esta: estatica
dina: dinamica

*************** Construyendo la librería estática argumentos.a ***************
gcc -Wall -I. -I/home/julio/include -L. -L/home/julio/lib -c -o argumentos.o argumentos.c
ar -rv libargumentos.a argumentos.o
ar: creating libargumentos.a
a – argumentos.o

*************** Construyendo pru_lib_argumentos_esta ***************
gcc -o pru_lib_argumentos_esta -Wall -I. -I/home/julio/include -L. -L/home/julio/lib pru_lib_argumentos.o -largumentos

Se meten en el programa, y las tienes siempre disponibles, pero que ocupa mas ya que estoy añadiendo al programa en si, la librería dentro. Osea si son pequeñas es bueno añadirla, pero si son grandes tu programa sera mas grande


*************** Construyendo la librería dinámica argumentos.so ***************
gcc -Wall -I. -I/home/julio/include -L. -L/home/julio/lib -c -o argumentos.o argumentos.c
ld -o libargumentos.so argumentos.o -shared
rm argumentos.o
*************** Construyendo pru_lib_argumentos_dina ***************
gcc -o pru_lib_argumentos_dina -Wall -I. -I/home/julio/include -L. -L/home/julio/lib pru_lib_argumentos.o -Bdynamic -largumentos

Las librerias dinámicas son librerias, que no engordan el programa, pero hay que distribuir el programa y la librería. Pero lo puedes reutilizar en otros programas esa librería.

El fichero que genera, siempre debe de estar disponible: argumentos.so


Explicamos los bloque del makefile: de argumentos.c ---> argumentos.a
*************** Construyendo la librería estática argumentos.a ***************
gcc -Wall -I. -I/home/julio/include -L. -L/home/julio/lib -c -o argumentos.o argumentos.c
ar -rv libargumentos.a argumentos.o
ar: creating libargumentos.a
a – argumentos.o

gcc -Wall -I. -I/home/julio/include -L. -L/home/julio/lib -c -o argumentos.o argumentos.c
De argumentos .c, he creado argumentos.o

ar -rv libargumentos.a argumentos.o
este comando es el que crea la librería.
“ar” es un compresor, empaqueta todos los archivos “.o” y crear un unico fichero “.a”
“-rv”, es un argumento que hace que reemplaza el “.a” por los “.o”, y si existen los reemplaza

ar: creating libargumentos.a
a – argumentos.o
Estos son mensajes los mensajes que nos da “ar”, al ponerle el argumento “-rv”, v=verbose, muestra los datos.

Nota:
El sistema obliba a que el nombre el nombre empieze por “lib” y termine por “a”

*************** Construyendo pru_lib_argumentos_esta ***************
gcc -o pru_lib_argumentos_esta -Wall -I. -I/home/julio/include -L. -L/home/julio/lib pru_lib_argumentos.o -largumentos
Esta linea se encarga de enlazar (falta el “-c” al “gcc”, no lo compila) con la librería se llama “libargumentos.a”, pero se pone como argumento argumentos, y -l junto “-largumentos”, y lo guarda con el nombre pru_lib_argumentos_esta.
El nombre del programa ejecutable es: pru_lib_argumentos_esta
Ahora vemos como lo hemos hecho para la librería dinámica.
*************** Construyendo la librería dinámica argumentos.so ***************
gcc -Wall -I. -I/home/julio/include -L. -L/home/julio/lib -c -o argumentos.o argumentos.c
ld -o libargumentos.so argumentos.o -shared
rm argumentos.o

la linea del gcc, es la misma que cuando era estática. Obtenemos el argumentos.o
El siguiente paso: comando ld
ld -o libargumentos.so argumentos.o -shared
ld: comado
-o: crear librería .so
-shared: compartida


*************** Construyendo pru_lib_argumentos_dina ***************
gcc -o pru_lib_argumentos_dina -Wall -I. -I/home/julio/include -L. -L/home/julio/lib pru_lib_argumentos.o -Bdynamic -largumentos

con esta linea, el programa ejecutable que creo es pru_lib_argmentos_dina

-Bdynamic: se mete antes de la librería este argumento,


Nota:
Se pueden usar mas de una librería, y de ambos tipos estaticas y dinamicas. Entonces, para este caso, si ponemos -Bdynamic: dice que todas las librerias que vengan a partir de ese arguentos son dinamicas y la palabra tecnica -static: indican que apartir de ese argumento sea estatico.

Cuando ejecutamos el compilado con librería dinámica nos sale:
julio@julio-Aspire-5735:~/Documentos/LIBRERIAS/ej_lib$ ./pru_lib_argumentos_dina
./pru_lib_argumentos_dina: error while loading shared libraries: libargumentos.so: cannot open shared object file: No such file or directory
julio@julio-Aspire-5735:~/Documentos/LIBRERIAS/ej_lib$

Este error es porque no ha encontrado el archivo libargumentos.so, ya que tiene que estar en un lugar adecuado (que solo tiene acceso el usuario root)

Se puede resolver de dos formas:
  1. Creamos una variable de entorno, llamada “LD_LIBRARY_PATH”, y ponemos la siguiente linea: (en la misma terminal donde estamos ejecutando el pru_lib_argumentos_dina)
    LD_LIBRARY_PATH=.
    export LD_LIBRARY_PAT
    y ya podemos ejecutar el archivo: ./pru_lib_argumentos_dina
  2. La copiamos en el sitio adecuado: /usr/lib

No hay comentarios:

Publicar un comentario en la entrada