43. Verwendung von Bibliotheken I

Die bisher besprochenen Funktionen kommen aus der Standard-C-Bibliothek (unter Unix meist /usr/lib/libc.a oder /lib/libc.a.b.c.so), die zu jedem C-Programm dazugelinkt wird. Es gibt viele andere nützliche Bibliotheken. Ein Beispiel ist die glib (nicht zu verwechseln mit der GNU C library glibc). Dokumentation dazu im Netz oder mit pinfo glib. Dass das nicht man glib ist, liegt daran, dass die GNU-MacherInnen man-pages (berechtigterweise) etwas angestaubt fanden und ihre Dokumentation in der Regel in TEXinfo schreiben, was zwar besser ist, aber zu mindestens zwei unabhängigen Dokumentationssystemen in der Unix-Welt geführt hat, eben man und info.

Flags

Wenn man eine Bibliothek benutzt,

  • muss der Linker wissen, welche Bibliotheken er woher dazulinken soll und
  • manchmal auch der Compiler, woher Headerfiles kommen sollen.
Diese Information bekommen Compiler und Linker wieder aus Flags, etwa -lglib, um die glib zu linken. Für die glib gibt es ein Programm, das diese Flags ausgibt: glib-config. Ein glib-Programm kann folgendermaßen kompiliert werden:
gcc   glib_hash.c -o glib_hash\
  ‘glib-config --cflags‘ ‘glib-config --libs‘

Leider haben die meisten Bibliotheken keine so netten Programme wie glib-config. Um Flags (und vieles andere) in einer halbwegs systematischen Weise erraten zu können, gibt es das erwähnte GNU autoconfig.

Ab Version 2 verwendet die glib ein Programm pkg-config, dessen Sinn ist, dass nicht jedes Programm ein eigenes xxx-config-Programm mitbringen, sondern nur eine Beschreibungsdatei an einer geeigneten Stelle hinterlassen muss. Wenn ihr nur eine so moderne glib habt, müsst ihr die Aufrufe an glib-config durch pkg-config --cflags glib bzw. pkg-config --libs glib ersetzen. Die Programme hier sollten auch mit der glib2 kompilierbar sein.

Übrigens führt ein Flag wie -lglib unter Unix dazu, dass der Linker Dateien wie libglib.a oder libglib.so sucht – den Präfix lib impliziert der Linker ebenso wie die Extensionen. Unter Windows sieht das im Groben ähnlich aus, die Extensionen sind aber eher LIB oder DLL.

Der Unterschied zwischen Bibliotheken mit Extensionen .a und .so ist, dass erstere statisch gelinkt werden, d.h., dass der Code der verwendeten Funktionen fest ins fertige Programm aufgenommen wird, während letztere dynamisch gelinkt werden. Dabei steht die Extension .so für “shared object”, was gleich einen Vorteil andeutet: Die Bibliothek wird unter allen Programmen im System geteilt, sogar im Speicher – statisch gelinkter Code steht im Programm und braucht separat Platz sowohl auf der Platte als auch im RAM. Die analoge Windows-Extension DLL heißt übrigens als Dynamically Loaded Library. Für die aus einer dynamischen Bibliothek gelinkten Funktionen stehen nur Namen im Produkt des Linkers. Erst wenn das Programm aufgerufen wird, werden diese Namen durch die Einsprungpunkte der Funktionen im shared object/der DLL ersetzt.

Nachteil des dynamischen Linkens: Wenn die shared objects gelöscht werden oder nur die Binärdatei ohne Bibliothek auf ein anderes System kommt, kann das Programm nicht mehr laufen. Vor allem unter Windows kommt noch das Versionsproblem dazu – auch Bibliotheken entwickeln sich mit der Zeit, und mit dieser Entwicklung ändern sich z.B. Datentypen und Prototypen. Wenn ein Programm gegen eine andere Version des shared objects gelinkt wurde, kann es wieder zu Abstürzen und Fehlfunktionen kommen – die berühmten DLL-Probleme. Unter Unix kann sowas auch ein Problem sein, durch eine etwas geschicktere Verwaltung und ein schlaueres Binärformat aber bei weitem nicht so oft – allerdings hat man hier häufig Probleme, wenn man C++-Bibliotheken mit verschiedenen Compilern baut.

Ein Makefile-Fragment für Programme mit glib:

CFLAGS += -Wall ‘glib-config --cflags‘
LDFLAGS += ‘glib-config --libs‘

Exkurs: Das lm-Problem

Aus historischen Gründen sind die mathematischen Funktionen häufig nicht in der Standardbibliothek selbst enhalten, sondern in einer Bibliothek namens libm. Das führt dazu, dass ein Programm wie

#include <math.h>
int main(void) { return (int)tan(M_PI); }

beim Linken Fehlermeldungen wie

/tmp/ccKcAW4r.o: In function ‘main':
/tmp/ccKcAW4r.o(.text+0x16): undefined reference
to ‘tan'
collect2: ld returned 1 exit status

liefert. Abhilfe schafft Linken mit -lm (im Makefile: LDFLAGS += -lm).


Markus Demleitner

Copyright Notice