(Dateien nach einer bestimmten Reihenfolge kompilieren) Linker-Fehler



  • 1.Datei

    //ieInitWindow.h
    //Initialisieren des Fensters
    #pragma once
    
    //Funktionen
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    ieResult InitWindow(int iWidth, int iHeight, char* cName, HICON hIcon);
    ieResult ExitWindow();
    ieResult MessageLoop(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    

    2.Datei

    //IEngine.h
    //Funktion:	Headerdatei der Engine	
    #pragma once
    
    #include <Math.h>
    ...
    #include <Windows.h>
    
    [...]
    enum ieResult
    {
    	IE_OK			=	0,
    	IE_ERROR		=	1,
    	IE_CANCELED		=	2,
    	IE_NOT_FOUND	=	3,
    	IE_STOP			=	4,
    };
    
    [...]
    
    //Die einzelnen Bestandteile hinzufügen
    #include "ieInitWindow.h"
    #include "ieVector3.h"
    

    Wenn jetzt die 1.Datei vor der 2. kompeliert wird, sind die ganzen Funktionen und Variablen nicht definiert


  • Mod

    Na und? Das Linken geschieht später, dann wenn alles bereits compiliert ist.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (auch C++0x) in das Forum Compiler- und IDE-Forum verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Nur so nebenbei: Den Vorgang nennt man "Kompilierung".



  • Der spuckt noch vor dem Linken die Fehler aus



  • Achso, das meinst du - dafür gibt es eine recht einfache Lösung: du schreibst deine Include-Anweisungen so, daß jeder die von ihm verwendeten Deklarationen erhält.



  • Also das ich bei ieInitWindow.h #include "IEngine.h" schreibe? Oder wie ist das gemeint?



  • Ja, und umgekehrt sind die #include's am Ende der IEngine.h vermutlich unnötig.



  • Dann kommen aber diese Fehler:

    1>Verknüpfen...
    1>IEngine.obj : error LNK2005: "__int64 ie_g_llFrequency" (?ie_g_llFrequency@@3_JA) ist bereits in ieInitWindow.obj definiert.
    1>IEngine.obj : error LNK2005: "int ie_g_bExitCalled" (?ie_g_bExitCalled@@3HA) ist bereits in ieInitWindow.obj definiert.
    1>IEngine.obj : error LNK2005: "int ie_g_bActivated" (?ie_g_bActivated@@3HA) ist bereits in ieInitWindow.obj definiert.
    1>IEngine.obj : error LNK2005: "double ie_g_dFrequency" (?ie_g_dFrequency@@3NA) ist bereits in ieInitWindow.obj definiert.
    1>IEngine.obj : error LNK2005: "double ie_g_dTime" (?ie_g_dTime@@3NA) ist bereits in ieInitWindow.obj definiert.
    1>IEngine.obj : error LNK2005: "struct HWND__ * ie_g_hWnd" (?ie_g_hWnd@@3PAUHWND__@@A) ist bereits in ieInitWindow.obj definiert.
    1>IEngine.obj : error LNK2005: "double ie_g_dNumSecsPassed" (?ie_g_dNumSecsPassed@@3NA) ist bereits in ieInitWindow.obj definiert.
    1>IEngine.obj : error LNK2005: "int ie_g_bInitCalled" (?ie_g_bInitCalled@@3HA) ist bereits in ieInitWindow.obj definiert.
    


  • Das sind alles Veriablen, die ich in IEngine.h definiert habe.



  • In einem Header definiert man ja auch keine Variablen - dort solltest du bestenfalls extern-Deklarationen verwenden (und deinem Projekt eine IEngine.cpp mit den Definitionen hinzufügen).



  • Das ist IEngine.h:

    //IEngine.h
    //Funktion:	Headerdatei der Engine	
    #pragma once
    
    #include <Windows.h>
    ...
    
    //Globale Variablen
     BOOL		ie_g_bInitCalled;		// Wurde die Engine initialisiert?
     BOOL		ie_g_bExitCalled;		// Wurde die Engine heruntergefahren?
     LONGLONG	ie_g_llFrequency;		// Frequenz des Zeitgebers
     double		ie_g_dFrequency;		// Frequenz des Zeitgebers (double)
     double		ie_g_dTime;				// Zeitzähler
     double		ie_g_dNumSecsPassed;	// Vergangene Sekunden seit letztem Frame
     BOOL		ie_g_bActivated;		// Ist das Fenster aktiv?
    ...
    
    //Rückgabewerte
    enum ieResult
    {
    	IE_OK			=	0,
    	IE_ERROR		=	1,
    	IE_CANCELED		=	2,
    	IE_NOT_FOUND	=	3,
    	IE_STOP			=	4,
    };
    
    //Die einzelnen Bestandteile hinzufügen
    #include "ieInitWindow.h"
    #include "ieVector3.h"
    #include "ieMatrix.h"
    ...
    

    Was habe ich jetzt falsch gemacht?



  • Dieser Header wird von mehreren Übersetzungseinheiten verwendet - da bekommt jede eine Kopie der definierten Variablen (und der Linker reagiert mit dem obengenannten Fehler). Das Zauberwort hier heißt "extern":

    //IEngine.h
    ...
    extern BOOL        ie_g_bInitCalled;        // Wurde die Engine initialisiert?
    ...
    
    //IEngine.cpp
    #include "IEngine.h"
    
    BOOL        ie_g_bInitCalled;        // Wurde die Engine initialisiert?
    ...
    


  • Bau mal Codeguards in deine Header.

    Header am Ende nicht gut, hat man schon geschrieben 😕

    MfG f.-th.



  • Vielen Dank! es klappt wieder! 😉



  • Hatte das falsche Stichwort 😡

    Das war gemeint:
    http://de.wikibooks.org/wiki/C-Programmierung:_Eigene_Header

    MfG f.-th.



  • f.-th. schrieb:

    Bau mal Codeguards in deine Header.

    Die Tuer schrieb:

    #pragma once

    Er braucht also keine (sofern er den Code nicht durch Compiler, die diese Direktive nicht unterstützen, jagen möchte).



  • Wenn ich jetzt aber in ein anderes Projekt das Engine-Projekt hinzufüge, kommen Linker-Fehler (Verweis auf nicht aufgelöstes externes Symbol ""enum ieResult __cdecl InitWindow(int,int,char *,struct HICON__ *,struct HINSTANCE__ *)" (?InitWindow@@YA?AW4ieResult@@HHPADPAUHICON__@@PAUHINSTANCE__@@@Z)" in Funktion "_WinMain@16 ...)

    IEngine.h

    ...
    #include"ieInitWindow.h"
    

    ieInitWindow.h

    #pragma once
    #include "IEngine.h"
    
    //Funktionen
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    ieResult InitWindow(int iWidth, int iHeight, char* cName, HICON hIcon, HINSTANCE hInst);
    

    ieInitWindow.cpp

    #include "ieInitWindow.h"
    ieResult InitWindow(int iWidth, int iHeight, char *cName, HICON hIcon, HINSTANCE hInst)
    {
    	[Definition der Funktion]
    }
    

    Test-Projekt
    Test.cpp

    #include "..\\..\\Engine\\Engine\\IEngine.h"
    
    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int ncmdshow)
    {
    	InitWindow(10, 10, "Name", NULL, hInst);
    	...
    
    }
    


  • Kann mir denn wirklich keiner helfen? 😞



  • Hast du denn deinem Projekt die "Engine.lib" hinzugefügt (ich nehme mal an, du hast eine statische bzw. dynamische Library erstellt)?

    Wenn nicht, dann mußt du auch noch die Engine-Sourcen deinem Projekt hinzufügen...

    P.S: "..\..\\Engine\\Engine\\IEngine.h" solltest du nicht verwenden, sondern in deinem Projekt den Pfad auf die Header-Dateien mitgeben (damit du nur noch "Engine\\IEngine.h" [bzw. noch besser "Engine/IEngine.h"] schreiben mußt).


Anmelden zum Antworten