6. Ulteriori esempi

Quelli che seguono sono altri esempi relativi alle tre modalità descritte (librerie statiche, condivise e a caricamento dinamico). Il file libhello.c implementa una semplice libreria con libhello.h come file di intestazione. Il file demo.c è un semplice file dimostrativo che contiene delle chiamate alla libreria. A questi seguono alcuni script commentati (script_static e script_shared) che illustrano l'uso della libreria come libreria statica e condivisa. Infine, demo_dynamic.c e script_dynamic mostrano come utilizzare la libreria condivisa come una libreria a caricamento dinamico.

6.1. File libhello.c

/* libhello.c - dimostrare l'uso di librerie. */

#include <stdio.h>

void hello(void) {
  printf("Hello, library world.\n");
}

6.2. File libhello.h

/* libhello.h - dimostrare l'uso di librerie. */


void hello(void);

6.3. File demo.c

/* demo.c -- dimostrare l'uso diretto della funzione "hello" */

#include "libhello.h"

int main(void) {
 hello();
 return 0;
}

6.4. File script_static

#!/bin/sh
# Esempio di libreria statica

# Crea il file oggetto della libreria statica, libhello-static.o.
# Uso il nome libhello-static per distinguerlo con chiarezza dagli
# esempi di librerie dinamiche, ma non è in generale necessario
# usare "-static" per i nomi di file oggetto che saranno parte
# di librerie statiche.

gcc -Wall -g -c -o libhello-static.o libhello.c

# Crea la libreria statica.

ar rcs libhello-static.a libhello-static.o

# A questo punto si potrebbe semplicemente copiare
# libhello-static.a da qualche altra parte per poi
# riutilizzarla. Per gli scopi dell'esempio ci si
# limiterà a lasciarla nella presente directory.

# Compilazione del file di programma demo.

gcc -Wall -g -c demo.c -o demo.o

# Creazione del programma demo; -L. fa sì che "." sia
# compresa nella ricerca durante la creazione del programma.
# Si noti che questo comando implica l'incorporazione del
# file libhello-static.a nel file demo_static.

gcc -g -o demo_static demo.o -L. -lhello-static

# Esecuzione del programma.

./demo_static

6.5. File script_shared

#!/bin/sh
# Esempio di libreria condivisa

# Crea il file oggetto della libreria condivisa, libhello.o.

gcc -fPIC -Wall -g -c libhello.c

# Crea la libreria condivisa.
# Si usi -lc per collegarla alla libreria del linguaggio C,
# dato che libhello dipende dalla libreria del C.

gcc -g -shared -Wl,-soname,libhello.so.0 \
    -o libhello.so.0.0 libhello.o -lc

# A questo punto potremmo semplicemente copiare libhello.so.0.0
# in qualche directory, ad esempio /usr/local/lib.

# Ora dobbiamo chiamare ldconfig per sistemare i link simbolici.

# Definizione del soname. Si potrebbe semplicemente eseguire:
# ln -sf libhello.so.0.0 libhello.so.0
# ma lasciamo che sia ldconfig a determinarlo

/sbin/ldconfig -n .

# Definizione del nome per il linker.
# In condizioni più complesse, ci si dovrebbe accertare
# dell'esistenza di un nome per il linker precedentemente
# definito ed in quel caso decidere se mantenerlo o meno.

ln -sf libhello.so.0 libhello.so

# Compilazione del file di programma demo.

gcc -Wall -g -c demo.c -o demo.o

# Creazione del programma demo.
# -L. aggiunge "." alle directory su cui effettuare la
# ricerca durante la creazione del programma; si noti che
# questo non significa che "." verrà controllata quando
# il programma viene eseguito.

gcc -g -o demo demo.o -L. -lhello

# Esecuzione del programma. Si noti che è necessario dire al
# programma dove trovare la libreria condivisa, utilizzando
# LD_LIBRARY_PATH.

LD_LIBRARY_PATH="." ./demo

6.6. File demo_dynamic.c

/* demo_dynamic.c -- dimostrare il caricamento dinamico e
   l'uso della procedura "hello" */


/* dlfcn.h è necessario per le funzioni di caricamento
   dinamico delle librerie */
#include <dlfcn.h>

#include <stdlib.h>
#include <stdio.h>

/* Si noti che non è necessario includere "libhello.h".
   Ad ogni modo occorre specificare alcune informazioni
   correlate; si deve specificare un tipo da associare
   al valore che si ricaverà da dlsym(). */

/* Il tipo "simple_demo_function" descrive una funzione
   che non prende alcun argomento, e non restituisce alcun
   valore: */

typedef void (*simple_demo_function)(void);


int main(void) {
 const char *errore;
 void *modulo;
 simple_demo_function demo_function;

 /* Carica dinamicamente la libreria */
 modulo = dlopen("libhello.so", RTLD_LAZY);
 if (!modulo) {
   fprintf(stderr, "Impossibile aprire libhello.so: %s\n",
           dlerror());
   exit(1);
 }

 /* Ricava il simbolo */
 dlerror();
 demo_function = dlsym(modulo, "hello");
 if ((errore = dlerror())) {
   fprintf(stderr, "Impossibile trovare hello: %s\n", errore);
   exit(1);
 }

 /* Ora chiama la funzione dalla libreria a caricamento
    dinamico */
 (*demo_function)();

 /* Tutto fatto, chiude in modo pulito */
 dlclose(modulo);
 return 0;
}

6.7. File script_dynamic

#!/bin/sh
# Dimostrazione di libreria a caricamento dinamico

# Presuppone che libhello.so e compagnia siano
# stati precedentemente creati (si vedano gli esempi
# precedenti).

# Compila il file programma demo_dynamic.c in un file
# oggetto:

gcc -Wall -g -c demo_dynamic.c

# Crea il programma demo_use.
# Si noti che non è necessario definire dove localizzare le
# librerie a caricamento dinamico dal momento l'unica libreria
# particolare utilizzata dal programma non verrà caricata se
# non dopo l'avvio.
# D'altro canto, è necessario utilizzare l'opzione -ldl per
# includere la libreria che implementa le funzioni per la
# gestione delle librerie a caricamento dinamico.

gcc -g -o demo_dynamic demo_dynamic.o -ldl


# Esecuzione del programma. Si noti che è necessario dire al
# programma dove trovare la libreria a caricamento dinamico,
# utilizzando LD_LIBRARY_PATH.

LD_LIBRARY_PATH="." ./demo_dynamic