auf8

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

auf8
Hy,
ich bin verwirrt mit dem Wort “Modul”.In jbuftest.c haben wir bei includes include <jbuffer.h> was O.K. ist,das ist also ein Modul.
Ist es genug dabei nur eine H-Datei jbuffer.h mit der Funktion jbuffer.c erzeugen und wenn ja was soll ich noch da haben,damit es funktioniert…
und aus mysem…soll ich die
Funktionen auch daraus in jbuffer.c aufrufen…und muss ich dann bei jbuffer.c mysem.c als include haben?
Gerade kriege ich so eine Meldung :
/tmp/ccpl0QKa.o(.text+0x0): In function sem_init': : multiple definition of sem_init’

liegt das Problem wirklich in meiner Verwirrung an includes?
Ich denke schon…


die Modularisierung unter C funktioniert folgendermaßen:

In der Header-Datei (.h) stehen die Datentypen, Makros und Funktionssignaturen des Modules, also nur die Deklaration. Um zu vermeiden, dass bei jedem include die Datei vom Präprozessor an diese Stelle kopiert wird, obwohl sie an anderer Stelle dem Compilier durch ein vorheriges include schon bekannt ist, sieht der Aufbau einer Header-Datei immer wie folgt aus (So vermeidet man unnötige Aufblähung des Quellcodes):

/*** Kopfkommentar ****/
#ifndef MODULE_H /* Makroname kann frei gewählt werden */
#define MODUEL_H

/* Datentypen, Makros, Funktionsdeklarationen (also ohne Implementierung) */

#endif

Die Implementierung der Funktionen steht in der (.c) Datei.

Möchte man nun Funktionen eines Moduls in eigenen Programmen/Modulen verwenden, so fügt man die entsprechende Header-Datei mittels der Präprozessor-Direktive #include in seine Datei ein. So sind alle dort deklarierten Datentypen (structs, globale Variablen), Makros und Funktionen in der eigenen Datei bekannt. (Der Präprozessor kopiert ja einfach nur den Inhalt der angegebenen Datei an die Stelle, an der die include Anweisung stand.)

Konkret bei jbuffer: In deiner jbuffer.h steht eigentlich lediglich

void jbuffer( int, int, int, int );
/* oder besser */
void jbuffer( int fd1, int fd2, int bufsize, int bufdelay);

In der mysem.h Datei stehen ebenfalls nur die Definition der Struktur SEM und die vier Funktionsdeklarationen. In der mysem.c Datei steht dann die Implementierung dieser Funktionen. Die zugehörige Include Datei sollte man auch immer in die implementierende .c Datei includen. Soll heißen mysem.c included mysem.h (muss es auch, wegen der Struktur SEM).

Der Fehler “multiple definiton” tritt auf, wenn du die .c Datei mit der Implementierung includest. Diese wird entweder in zwei Module reinkopiert oder du gibst beim Übersetzen (wie auch richtig) die .c Datei mit an. Das hat aber zur Folge, dass der Linker zwei Funktionen in verschiedenen Objektdateien findet, die die gleiche Signatur haben (es handelt sich ja in beiden Fällen um tatsächlich die gleiche Funktion).

Also: Nur die Header-Datei mit den Deklarationen includen, nie die .c Datei mit der eigentlichen Implementierung (Definition).

Leider fällt es mir schwer das klar verständlich auszudrücken, mir scheint, das ganze mag etwas verwirrend klingen. Vielleicht bringt noch jemanden etwas Klarheit hinter meine Erklärung.


Ein Modul besteht normalerweise aus mindestens einer Headerdatei und natuerlich der Implementierung. Diese kann entweder nur als Object-Datei oder als C-Quelldatei vorliegen, bzw. geschrieben werden.
Um das Modul dann woanders zu verwenden muss man

  1. In der C-Quelldatei, in der man das verwendet, den entsprechenden header includen, damit der Compiler weis, welche Parameter die Funktionen haben und was sie zurueckliefern. (das hast du schon gemacht).
    Hier geht es nur ums kompilieren, das schaut dann so aus:
gcc -c myFile.c
gcc -c myModule.c
  1. Allerdings muss der Funktionsrumpf (also die eigentliche Implementierung) ja auch irgendwo herkommen, also am Ende zu der ausfuehrbaren Datei dazugelinkt werden. Wenn man hier entwas vergessen hat, dann kommen diese beruehmt beruechtigten “undefined references”, wenn man entwas doppelt hat “multiple definition”.
    Die Zeile zum Linken schaut ueblicherweise so aus:
gcc -o myExecutable myFile.o myModule.o

Wenn man Systembibliotheken dazulinken will, die nicht in der libC enthalten sind, dann muss man das explizit angeben, mit den Paramtern -l (und evtl -L), dies ist z.B. bei den pthreads der Fall.

gcc -o myExecutable myFile.o -lpthread

In diesem Fall sucht der linker eine Datei libpthread.a im System. Falls die Bibliothek an einer exklusiven Stelle liegt muss man mit -L/path/to/lib/ noch angeben, wo die liegt, das ist bei uns aber nicht der Fall.

Ich vermute, dass du in dem header file bereits die Implementierung reingeschrieben hast, obwohl da nur der Funktionsrumpf reingehoert:

SEM *sem_init(int n);

Danke
Danke