getrennte Kompilierung / überkreuzende Bezüge [erledigt]



  • Hi

    Ich habe nun versucht, ein Programm, das aus 2 Datein besteht getrennt zu kompilieren. Die 1. Datei verwendet eine Funktion aus der 2. Datei. Also habe ich in der 1. Datei eine #include-Anweisung geschrieben.

    Wenn ich die beiden Dateien miteinander kompiliere, dann funktioniert alles perfekt. Ich kann auch beide einzeln kompilieren ohne sie zu linken. (g++ -c datei.cpp) Wenn ich sie dann linken möchte (g++ -o result.exe datei1.o datei2.o) dann gibt es eine Fehlermeldung.
    Der Grund dafür ist mir auch klar: In der ersten *.o-Datei sind beide Quelldateien enthalten, da die #include-Anweisung die 2. Datei ja einfügt.
    Aber wie kann ich dies umgehen? Das #include brauche ich, sonst kann ich die Dateien nicht kompilieren...
    Wenn ich nur Variablen verwende, dann könnte ich ja "extern" verwenden, aber mit Funktionen geht das ja nicht...

    Das 2. Problem ist:
    Ich habe wieder 2 Dateien. Jede Datei verwendet eine Funktion aus der anderen Datei. Wenn ich in jeder eine #include-Anweisung auf die andere mache, dann gibts ne Katastrophe...

    cu
    Jonny



  • Du mußt die header-Dateien einbinden und nicht den Quell-Code.
    In den Header-Dateien müssen dann deine Funktionen deklariert sein.
    Der eingentliche Inhalt mit allen Anweisungen erfolgt dann in den jeweiligen C/C++-Dateien.



  • unregistrierter schrieb:

    Du mußt die header-Dateien einbinden und nicht den Quell-Code.
    In den Header-Dateien müssen dann deine Funktionen deklariert sein.
    Der eingentliche Inhalt mit allen Anweisungen erfolgt dann in den jeweiligen C/C++-Dateien.

    Und wie mache ich das? Ich hab mal versucht, einfach .h-Dateien mit dem gleichen Namen anzulegen, die die Deklarationen enthalten. Aber es funktioniert nicht...

    Edit:
    ES funktioniert, aber nur, wenn ich die Dateien getrennt kompiliere. Sonst kommt die Meldung "undefined reference to <funktionsname>"



  • Zeig mal ein bisschen Code.

    In die .h-Dateien gehören u.a. die Prototypen der Funktionen, die in der jeweils anderen Datei stehen.



  • DeWinter schrieb:

    Wenn ich nur Variablen verwende, dann könnte ich ja "extern" verwenden, aber mit Funktionen geht das ja nicht...

    Doch natürlich:

    // Datei1.c
    int x = 0; // globale Var.
    void func() {
      //blabla
    }
    
    // Datei2.c
    extern int x;
    void func(void); // extern kann dazu geschrieben werden, ist aber implizit
    
    void blub() {
      // blubblub
      func();
    }
    

    Normalerweise macht man das jetzt so, dass man die Deklarationen nicht manuell einfügt wie ich hier, sondern in eine Headerdatei schreibt, die man dann dort includiert, wo man sie braucht.



  • Danke für die Antworten! 🙂

    Datei main.cpp

    #include "hello.h"
    
    int main(int argc, char **argv)
    {
      PrintHello();
      PrintBye();
    
      return 0;
    }
    

    Datei hello.h

    void PrintHello(void);
    void PrintBye(void);
    

    Datei hello.cpp

    #include <iostream>
    using namespace std;
    
    void PrintHello(void)
    {
      cout << "hello world" << endl;
    }
    
    void PrintBye(void)
    {
      cout << "bye bye world" << endl;
    }
    

    Wenn ich das folgerndermassen compiliere, dann funktionierts auch:
    g++ -c main.cpp
    g++ -c hello.cpp
    g++ main.o hello.o

    Wenn ichs aber so versuche

    g++ main.cpp

    dann funktioniert es nicht. Meldung:

    C:/Dokume1/FEller1/Lokale~1/Temp/ccoBaaaa.o/. text+0x1f): main.cpp unfedined reference to 'PrintHello()'

    und dasselbe für PrintBye().



  • DeWinter schrieb:

    g++ main.cpp
    C:/Dokume1/FEller1/Lokale~1/Temp/ccoBaaaa.o/. text+0x1f): main.cpp unfedined reference to 'PrintHello()'

    Klar, PrintHello ist ja auch nicht in main.cpp definiert. Wenn du alle Sourcefiles auf einmal übersetzt, geht es:

    g++ main.cpp hello.cpp

    Besser ist aber die getrennte Compilierung in einzelne .o Files, sonst können die Compilierzeiten schnell astronomische Ausmaße annehmen. Mach dich am besten mit dem Tool make vertraut, das sorgt dafür, dass jeweils nur die Sourcefiles neu compiliert werden, die sich verändert haben oder die von veränderten Dateien abhängig sind.



  • OK, vielen Dank!

    Aber noch eine Frage:

    #include <GL\Glut.h>
    #include <stdlib.h>
    
    void display(void);
    void init(void);
    
    void display(void) 
    {
      glClear(GL_COLOR_BUFFER_BIT);
    
      glColor3f(1.0, 1.0, 1.0);
      glBegin(GL_POLYGON);
        glVertex3f(0.25, 0.25, 0.0);
        glVertex3f(0.75, 0.25, 0.0);
        glVertex3f(0.75, 0.75, 0.0);
        glVertex3f(0.25, 0.75, 0.0);
      glEnd();
      glFlush();
    }
    
    void init(void)
    {
      glClearColor(0.0, 0.0, 0.0, 0.0);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
    }
    
    int main(int argc, char **argv)
    {
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
      glutInitWindowSize(250, 250);
      glutInitWindowPosition(100, 100);
      glutCreateWindow("hello");
      init();
      glutDisplayFunc(display);
      glutMainLoop();
    
      return 0;
    
    }
    

    Dieser Code bringt wieder die gleichen Fehlermeldungen wie oben beschrieben. (undefined reference to <blabla>) Also dachte ich, ich könne es auf die gleiche Art lösen. (also die Glut-Datei auch kompilieren und dazu linken) Aber welches ist die richtige Datei? Ich habe auf meinem System folgende Dateien gefunden:

    Glut.h
    glut32.lib
    libglut.a
    libglut32.a
    glut32.dll

    aber keine .o oder .cpp Datei...



  • Da musst du in die Doku der glut-Library gucken. Libraries bindet man allgemein mit dem Parameter -l<name> ein, wobei <name> der Dateiname ohne lib und .a ist, also -lglut für libglut.a. Aber welche du brauchst usw. -> Doku



  • Langsam blick ich nicht mehr durch...
    Wieso muss ich, wenn ich GLUT verwenden will, noch eine Library mitlinken? Wieso muss ich das sonst nicht? Und was ist der Unterschied zwischen .o .a .dll Dateien? Irgendwo hab ich mal gelesen, dass eine .h und die dazugehörige .cpp Datei eine Bibliothek bilden. Stimmt das?

    Und konkrekt zu meinem Problem:
    Es gibt nur die glut32.dll und die glut32.lib. Ich hab dann nach der Anleitung auf www.mingw.org die glut32.lib (die IMHO für den MSVC ist) in eine minGW-Datei verwandelt (libglut32.a). Aber das hat auch nichts genutzt...



  • DeWinter schrieb:

    Wieso muss ich, wenn ich GLUT verwenden will, noch eine Library mitlinken?

    Weil GLUT eine Library ist.

    Wieso muss ich das sonst nicht?

    Weil du sonst keine Zusatzlibraries verwendest.

    Und was ist der Unterschied zwischen .o .a .dll Dateien?

    .o Files sind Objectfiles, übersetzte Sourcefiles
    .a sind Sammlungen (Archive) von .o Files, auch als statische Bibliothek bekannt
    .dll sind dynamische Bibliotheken, die erst während der Programmausführung gelinkt werden (ganz ganz grob)

    [quote
    Irgendwo hab ich mal gelesen, dass eine .h und die dazugehörige .cpp Datei eine Bibliothek bilden. Stimmt das?[/quote]

    Nicht wirklich, obwohl es nicht gänzlich falsch ist. Aber eine .cpp Datei mit allen Headern ist zunächst mal nur eine Übersetzungseinheit, die dann zu einem Objectfile übersetzt wird. Von Bibliotheken spricht man normalerweise erst bei größeren Modulen, die primär nicht dazu da sind, allein ausgeführt zu werden, sondern die statisch oder dynamisch in andere Programme eingebunden werden.



  • Was ist denn z.B. "iostream.h"? Ich habe ja folgende 2 Anweisungen:
    #include <iostream.h>
    #include <GL\GLUT.H>

    Das erste genügt dazu, dass ich alle funktionen, die in "iostream.h" deklariert sind zu gebrauchen. [Zwischenfrage: iostream.h ist doch nur eine Headerdatei. Da müsste noch eine .cpp-Datei existieren. Aber 1. kann ich keine finden und 2. wäre die schon vorkompiliert? Ich muss ja nicht bei jedem Programm jede include-Datei mitkompilieren...].
    Das 2. genügt ja anscheinend nicht, ich muss, wie du gesagt hast, dem Compiler noch extra eine Library angeben.

    Und wo ist jetzt der Unterschied? Also technisch gesehen?



  • die zu iostream.h (übrigens: iostream.h ist veraltet, heute benutzt man eigentlich iostream) gehörenden Implementierungen sind in der Standardbibliothek. Der Compiler bindet die automatisch mit ein, ausser man schaltet das explizit ab. Die von GLUT sind in einer extra Bibliothek, die mußt du folglich manuell dazubinden.

    Wär das nicht so, müßtest du sowas wie 'g++ eins.o zwei.o -lstdc++' aufrufen.



  • Sehe ich das richtig, dass Bibliotheken vers. Compiler nicht unbedingt kompatibel miteinander sind? In der Glut-Zip-Datei sind .lib Dateien drin, die für den MSVC gedacht sind. Dort steht auch, dass man die Library für den Borland Compiler konvertieren kann. Ich hab in der FAQ auf www.mingw.org etwas ähnliches gefunden und nach der Anleitung die Library konvertiert. (Kann es sein, dass die .dll-Dateien im gegensatz zu den statischen Bibliotheken kompatibel sind?)
    Wenn ich nun versuche, dass Programm zu kompilieren, kommt die Meldung:
    ld: cannot find -lglut32

    mit ld --help konnte ich leider nichts herausfinden, noch nicht einmal, was ld überhaupt macht...



  • DeWinter schrieb:

    Sehe ich das richtig, dass Bibliotheken vers. Compiler nicht unbedingt kompatibel miteinander sind?

    Jup.

    Kann es sein, dass die .dll-Dateien im gegensatz zu den statischen Bibliotheken kompatibel sind?

    Jup. Das DLL-Handling wird von Windows zur Verfügung gestellt.

    ld: cannot find -lglut32

    Das könnte bedeuten, dass du keine libglut32.a hast. ld ist übrigens der Linker, der irgendwann von g++ aufgerufen wird.



  • Vielen Dank. Ich glaube, jetzt kann ich es schaffen!


Anmelden zum Antworten