Premessa

Le informazioni qui riportate sono state prese dal sito Linux Tutorial - Static, Shared Dynamic and Loadable Linux Libraries e successivamente testate e personalizzate dal gruppo controlli della divisione acceleratori.

Una procedura rapida per compilare una libreria dinamica e' la seguente, dato un file .c:

gcc -o <fileName>.so ./<fileName>.c -I/path/with/include/files/ -l<lib_to_include> -shared

Ad esempio, per lavorare con il VME, il comando cambia in questo modo:

gcc -o <fileName>.so ./<fileName>.c -I/usr/local/lv70/cintools/ -lvme -shared

Se invece si vuole utilizzare la procedura standard di Linux per creare le librerie dinamiche, seguire i step riportati qui di seguito:

Creazione della struttura delle directory

Per creare una struttura base per una libreria bastano poche cartelle. Ad esempio, per una libreria che chiameremo libadc (lo standard linux prevede che una libreria inizi con il prefisso lib) basta lanciare i seguenti comandi (in questo caso, lavoriamo su di una VMIC nella cartella home dell'utente dante):

[dante@dante076 dante]$ mkdir -p ./libadc/include
[dante@dante076 dante]$ mkdir ./libadc/source

Nella cartella include andremo ad inserire l'header file della libreria, mentre nella cartella source andremo a creare tutti i sorgenti che andranno a formare la nostra libreria.

(info) Nota: la creazione di queste cartelle non è indispensabile alla compilazione della libreria, ma permette di organizzare meglio il progetto in modo tale che al crescere dei file sorgenti la struttura resti chiara, pulita e definita.

Creazione del codice della libreria

Per creare una libreria abbiamo bisogno di scrivere il sorgente che andra' ad essere compilato come libreria ed un file di header con i prototipi di tutte le funzioni implementate dalla libreria. In questo esempio base, andremo a creare una libreria fatta da un unico file sorgente (adc.c). Di conseguenza avremo i seguenti file:

/home/dante/libadc/source/adc.c
void adc_read (int *i) {
   *i = 5;
}
/home/dante/libadc/include/adc.h
#ifndef ADC_H
#define ADC_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
void adc_read(int *);
 
#ifdef __cplusplus
}
#endif
 
#endif

Come si può notare, l'unica funzione presente in adc.c (e quindi nella libreria) non fa altro che settare a 5 una variabile passatagli per indirizzo. Nell'header file invece andiamo a dichiarare il prototipo dell'unica funzione implementata dalla libreria; si usa anche la notazione extern "C" così che la libreria possa essere usata sia da codice C che da codice C++.

Compilazione della libreria

Per compilare la libreria in modo dinamico, basta lanciare i seguenti comandi:

[dante@dante076 dante]$ cd libadc
[dante@dante076 libadc]$ gcc -Wall -fPIC -c ./source/adc.c
[dante@dante076 libadc]$ gcc -shared -Wl,-soname,libadc.so.1 -o libadc.so.1.0 adc.o
[dante@dante076 libadc]$ rm adc.o
[dante@dante076 libadc]$ ln -sf /home/dante/libadc/libadc.so.1.0 /home/dante/libadc/libadc.so
[dante@dante076 libadc]$ ln -sf /home/dante/libadc/libadc.so.1.0 /home/dante/libadc/libadc.so.1

Nel primo comando gcc utilizziamo le seguenti opzioni:
-Wall: Visualizza a video tutti i possibili warning di compilazione;
-fPIC: Crea codice "position-independent", necessario per le librerie dinamiche;

Nel secondo comando gcc andiamo a passare le seguenti opzioni:
-shared: Crea la libreria vera e propria, ossia uno "shared object" (.so) che puo' essere linkato ad altro codice per formare un eseguibile;
-Wl: Passa delle opzioni al linker. In questo caso le opzioni passate sono -soname libadc.so.1;
-o: Specifica il nome della libreria;

I link simbolici invece servono rispettivamente per:
libadc.so: Permette di linkare la libreria con il flag -ladc in fase di inclusione di questa libreria in altro codice;
libadc.so.1: Permette al "runtime binding" di funzionare ( (question) );

A questo punto la libreria è pronta per l'uso. Per completezza, mostriamo come creare un programma di prova che viene compilato con la libreria appena scritta.

Creazione di un programma di test

Scriviamo un programma di test che utilizzi la libreria appena creata:

/home/dante/main.c
#include <stdio.h>
#include "adc.h"
 
int main () {
   int x;
   adc_read (&x);
   printf ("Valx=%d\n", x);
 
   return 0;
}

Compilazione del programma di test

Per compilare il programma di test, lanciare i seguenti comandi:

[dante@dante076 libadc]$ cd /home/dante
[dante@dante076 dante]$ gcc -Wall -I/home/dante/libadc/include -L/home/dante/libadc main.c -ladc -o main

Run del programma di test

Per eseguire il programma, serve definire dove si trova la libreria (perchè non è in nessuna cartella in cui il sistema se la aspetta) e poi si può lanciarlo. Per fare questo, lanciare i seguenti comandi:

[dante@dante076 dante]$ export LD_LIBRARY_PATH=/home/dante/libadc:$LD_LIBRARY_PATH
[dante@dante076 dante]$ ./main
  • No labels