Librerías en C

3
Librerías estáticas y dinámicas Según vamos haciendo programas de ordenador, nos damos cuenta que algunas partes del código se utilizan en muchos de ellos. Por ejemplo, podemos tener varios programas que utilizan números complejos y las funciones de suma, resta, etc son comunes. También es posible, por ejemplo, que nos guste hacer juegos, y nos damos cuenta que estamos repitiendo una y otra vez el código para mover una imagen (un marcianito o a Lara Croft) por la pantalla. Sería estupendo poder meter esas funciones en un directorio separado de los programas concretos y tenerlas ya compiladas, de forma que podamos usarlas siempre que queramos. Las ventajas enormes de esto son: No tener que volver a escribir el código (o hacer copy-paste). Nos ahorraremos el tiempo de compilar cada vez ese código que ya está compilado. Además, ya sabemos que mientras hacemos un programa, probamos y corregimos, hay que compilar entre muchas y "más muchas" veces. El código ya compilado estará probado y será fiable. No las primeras veces, pero sí cuando ya lo hayamos usado en 200 programas distintos y le hayamos ido corrigiendo los errores. La forma de hacer esto es hacer librerías. Una librería son una o más funciones que tenemos ya compiladas y preparadas para ser utilizadas en cualquier programa que hagamos. Hay que tener el suficiente ojo cuando las hacemos como para no meter ninguna dependencia de algo concreto de nuestro programa. Cómo tenemos que organizar nuestro código Para poder poner nuestro código en una librería, necesitamos organizarlo de la siguiente manera: Uno o más ficheros fuente .c con el código de nuestras funciones.

description

Librerías en C dinámicas

Transcript of Librerías en C

Page 1: Librerías en C

Librerías estáticas y dinámicas

Según vamos haciendo programas de ordenador, nos damos cuenta que algunas partes del código se utilizan en muchos de ellos. Por ejemplo, podemos tener varios programas que utilizan números complejos y las funciones de suma, resta, etc son comunes. También es posible, por ejemplo, que nos guste hacer juegos, y nos damos cuenta que estamos repitiendo una y otra vez el código para mover una imagen (un marcianito o a Lara Croft) por la pantalla.

Sería estupendo poder meter esas funciones en un directorio separado de los programas concretos y tenerlas ya compiladas, de forma que podamos usarlas siempre que queramos. Las ventajas enormes de esto son:

No tener que volver a escribir el código (o hacer copy-paste). Nos ahorraremos el tiempo de compilar cada vez ese código que ya está

compilado. Además, ya sabemos que mientras hacemos un programa, probamos y corregimos, hay que compilar entre muchas y "más muchas" veces.

El código ya compilado estará probado y será fiable. No las primeras veces, pero sí cuando ya lo hayamos usado en 200 programas distintos y le hayamos ido corrigiendo los errores.

La forma de hacer esto es hacer librerías. Una librería son una o más funciones que tenemos ya compiladas y preparadas para ser utilizadas en cualquier programa que hagamos.  Hay que tener el suficiente ojo cuando las hacemos como para no meter ninguna dependencia de algo concreto de nuestro programa.

Cómo tenemos que organizar nuestro código

Para poder poner nuestro código en una librería, necesitamos organizarlo de la siguiente manera:

Uno o más ficheros fuente .c con el código de nuestras funciones. Uno o más ficheros de cabecera .h con los tipos (typedefs, structs y enums) y prototipos

de las funciones que queramos que se puedan utilizar.

Como siempre, vamos a hacer un ejemplo. Los ficheros serían estos:

libreria1.h#ifndef _LIBRERIA_1_H #define _LIBRERIA_1_Hint suma (int a, int b);int resta (int a, int b);#endiflibreria1.cint suma (int a, int b){ return a+b;}int resta (int a, int b){

Page 2: Librerías en C

return a-b;}

Es un fichero con un par de funciones simples de suma() y resta().

Un detalle importante a tener en cuenta, son los #define del fichero de cabecera (.h). Al hacer una librería, no sabemos en qué futuros programas la vamos a utilizar ni cómo estarán organizados. Supongamos en un futuro programa que hay un fichero de cabecera fichero1.h que hace #include del nuestro. Imaginemos que hay también un fichero2.h que también hace #include del nuestro. Finalmente, con un pequeño esfuerzo más, imaginemos que hay un tercer fichero3.c que hace #include de fichero1.h y fichero2.h, es decir, más o menos lo siguiente:

fichero1.h#include <libreria1.h>...fichero2.h#include <libreria1.h>...fichero3.c#include <fichero1.h>#include <fichero2.h>...

Cuando compilemos fichero3.c, dependiendo de lo que haya definido en libreria1.h, obtendremos un error. El problema es que al incluir fichero1.h, se define todo lo que haya en ese fichero, incluido lo de libreria1.h. Cuando se incluye fichero2.h, se vuelve a intentar definir lo contenido en libreria1.h, y se obtiene un error de que esas definiciones están definidas dos veces.

La forma de evitar este problema, es meter todas las definiciones dentro de un bloque #ifndef - #endif, con el nombre (_LIBRERIA_1_H en el ejemplo) que más nos guste y distinto para cada uno de nuestros ficheros de cabecera. Es habitual poner este nombre precedido de _, acabado en _H y que coincida con el nombre del fichero de cabecera, pero en mayúsculas.

Dentro del bloque #ifndef - #endif, hacemos un #define de ese nombre (no hace falta darle ningún valor, basta con que esté definido) y luego definimos todos nuestros tipos y prototipos de funciones.

Cuando incluyamos este fichero por primera vez, _LIBRERIA_1_H no estará definido, así que se entrará dentro del bloque #ifndef - #endif y se definirán todos los tipos y prototipos de funciones, incluido el mismo _LIBRERIA_1_H. Cuando lo incluyamos por segunda vez, _LIBRERIA_1_H ya estará definido (de la inclusión anterior), por lo que no se entrará en el bloque #ifndef - #endif, y no se redefinirá nada por segunda vez.

Es buena costumbre hacer esto con todos nuestros .h, independientemente de que sean o no para librerías. Si te fijas en algún .h del sistema verás que tienes este tipo de cosas hasta aburrir. Por ejemplo, en /usr/include/stdio.h, lo primero que hay después de los comentarios, es un #ifndef _STDIO_H.