Sign in to follow this  
Zeraan

Problem with including header files

Recommended Posts

Zeraan    317
ok, I've managed to fix my DirectX engine, so when I include it, it doesn't give errors, and everything's working smoothly now. Now I'm trying to divide the program into different files such as Game_Init, Game_Main, etc. The only way I can see to do that is to declare the D3D class in WinMain.cpp (where the WinMain function is, obiviously) but as a global in that file, then pass it to other functions. I think I've forgotten how to pass it through functions, due to errors that I've recieved. I feel like a noobie again :( I tried it like this:
function header: (in GameMain.h)

bool Game_Init(TGraphic*, HWND, int, int); //TGraphic is D3D engine, two ints is size of screen

function prototype: (in GameInit.cpp)

bool Game_Init(TGraphic* Graphic, HWND hWnd, int width, int height)
{
...
}

function call: (in WinMain.cpp)

if(!Game_Init(Graphic, g_hWnd, 800, 600))
		return 0;
Where am I going wrong? Thanks! *Edit, this problem is resolved, scroll to bottom for more details. [Edited by - Zeraan on July 2, 2005 1:11:57 AM]

Share this post


Link to post
Share on other sites
Zeraan    317
never mind, I think I got it right. I removed the * pointers, and it seems to work. But the problem is, I had to include the d3d engine "outpost.h" in both GameMain.h and GameInit.h to get it to work, or have GameInit.h include GameMain.h, but every time I do that, I get 74 errors basically saying that I'm redefining the stuff in D3D that've been already defined. I think I did something wrong in creating the .h files?

one of the errors looks like this:

GameInit.obj : error LNK2005: "public: __thiscall TParticle::TParticle(void)" (??0TParticle@@QAE@XZ) already defined in WinMain.obj

it's the same with every function in all of the engine.

the Outpost.h looks like this:

#ifndef OUTPOST
#define OUTPOST

#include <d3d8.h>
#include <d3dx8.h>
#include <dinput.h>
#include <dplay8.h>
#include <dpaddr.h>

#include "OutpostG.h" //Graphic
#include "OutpostI.h" //Input

#endif


The outpost.h is included in gamemain.h, which is included in Winmain.cpp. So if I include the same file in other .cpp, would that cause problems?

the #ifndef OUTPOST should have taken care of this problem?

Share this post


Link to post
Share on other sites
Oberon_Command    6075
For all your variables that are declared in header files, make sure to use the extern keyword to declare them, then declare the variables themselves in another source file. Like so:


// header

extern int whatever;




// source file
int whatever = 0;



// sourcefile 2
int main()
{
cout << whatever << endl;
}

Share this post


Link to post
Share on other sites
Zeraan    317
in OutpostG.h and OutpostI.h, theres no variables, except for classes, and those classes are defined in their source files. So I have to add extern to those classes? I'll try it now, correct me if I'm wrong. Thanks for the advice, I'll keep that in mind.

Share this post


Link to post
Share on other sites
Zeraan    317
ok, the result of extern is that it will get ignored if put next to class:

...\outpost\outposti.h(42) : warning C4091: 'extern ' : ignored on left of 'class TOutpost_Input' when no variable is declared

Share this post


Link to post
Share on other sites
Zeraan    317
A thought hits me. What if the fact that the .h files in my Outpost engine includes the .cpp files is the source of the problems? Because when I reinclude it in another .cpp file, it also reincludes the .cpp files, thereby redefining the functions. I think that might be the cause. How would I go around to fix this problem? Add #ifndef to .cpp files? :)

My goal is to make a DirectX engine that is independent of the game, so I can reuse it again easily. Thanks for your help.

Share this post


Link to post
Share on other sites
Zeraan    317
I'm still stumped on this... Any ideas or suggestions? I've tried looking up tutorials, but apparently they didn't have tutorials on this. I'll continue research on this, if someone will be willing to help, I will really appreciate it!

This is an example error message:
WinMain.obj : error LNK2005: "public: __thiscall TParticle::TParticle(void)" (??0TParticle@@QAE@XZ) already defined in GameInit.obj

WinMain.cpp included the Outpost.h, and when I include it in GameInit also, I get those error messages. One for each function in the engine.

Share this post


Link to post
Share on other sites
JWindebank    156
Do you have the inclusion guards in all of your header files? Also are you declaring variables used throughout multiple files with the extern command?

Could you post a copy of WinMain.cpp, Outpost.h and Outpost.cpp please?

Share this post


Link to post
Share on other sites
Xai    1838
i'm totally confused. What are you including you .cpp files for? While C++ has no formal rules on file extensions, the idea behind .h and .cpp is that the .h extension is used for things which are meant to be #included into other files (declarations of class, functions, and extern variables) and .cpp is meant to be used for things that are supposed to be compiled (implementations of functions and allocation of variables).

please post a post with a little tree showing what files are including what ... like this:

MyClass.h: nothing
MyClass.cpp: MyClass.h
AnotherClass.h: MyClass.h
AnotherClass.cpp: AnotherClass.h
Main.cpp: Myclass.h, AnotherClass.h

and then if you want you can tell us where the relevant parts are ...

btw, the #ifndef guards are for dealing with the situation where a header file is included in more than 1 HEADER file, not more than 1 cpp file. Look at my example above and you will see MyClass.h is included in MyClass.cpp, AnotherClass.h, and Main.cpp. The inclusions in MyClass.cpp and Main.cpp do not interfere with each other, if you headers only contain what the should ... but the inclusion in AnotherClass.h causes it to end up in Main.cpp twice ... which is not good .... hence the use of inclusion guards.

Each .cpp file is compiled COMPLETELY SEPERATELY from every other .cpp file ... hence the reason you have to #include <list> in EVERY .cpp file that uses a list, not just any 1 file in your project.

Share this post


Link to post
Share on other sites
Zeraan    317
Yes, I've included inclusion guards. Here's the source code:


////////////////////////////////////////////////////////////////////////////
GameMain.h
////////////////////////////////////////////////////////////////////////////

#ifndef GAMEMAIN
#define GAMEMAIN

#include <windows.h>
#include "C:\Games\Brent's Games\Outpost\Outpost.h"

bool Game_Init(/*TOutpost_Graphic, */HWND, int, int);
bool Game_Main();
void Game_End();

#endif

////////////////////////////////////////////////////////////////////////////
GameInit.cpp
////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "C:\Games\Brent's Games\Outpost\Outpost.h"

bool Game_Init(/*TOutpost_Graphic Graphic, */HWND hWnd, int Width, int Height)
{
if(!Graphic.D3D_Init(hWnd, 800, 600))
return false;

return true;
}

////////////////////////////////////////////////////////////////////////////
WinMain.cpp
////////////////////////////////////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN

#define DIRECTINPUT_VERSION 0x0800

#include <windows.h>
#include "GameMain.h"

...

TOutpost_Graphic Graphic;

...

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
...
if(!Game_Init(Graphic, g_hWnd, 800, 600))
//error message
}

...

////////////////////////////////////////////////////////////////////////////
Outpost.h
////////////////////////////////////////////////////////////////////////////

#ifndef OUTPOST
#define OUTPOST

#include <d3d8.h>
#include <d3dx8.h>
#include <dinput.h>
#include <dplay8.h>
#include <dpaddr.h>

#include "OutpostG.h" //Graphic
#include "OutpostI.h" //Input

#endif

////////////////////////////////////////////////////////////////////////////
OutpostG.h (there's no Outpost.cpp)
////////////////////////////////////////////////////////////////////////////

#ifndef OUTPOSTG
#define OUTPOSTG

#include <d3d8.h>
#include <d3dx8.h>
#include "Outpost.h"
#include "TParticle.h"

#define WThinLine_FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
#define SThinLine_FVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

#define PolyObject_FVF (D3DFVF_XYZ | D3DFVF_TEX1)

#define POINT_LIGHT 0
#define DIRECTIONAL_LIGHT 1

class declarations from this point.

...

#include "OutpostG.cpp"

#endif

////////////////////////////////////////////////////////////////////////////
OutpostI.h
////////////////////////////////////////////////////////////////////////////

#ifndef OUTPOSTI_H
#define OUTPOSTI_H

#include <dinput.h>
#include "Outpost.h"

#define LEFT_BUTTON 0
#define RIGHT_BUTTON 1
#define MIDDLE_BUTTON 2

#define MouseButtonState(x) ((m_MouseState.rgbButtons[x] & 0x80) ? TRUE : FALSE)

class TOutpost_Input
{
private:

UCHAR keystate[256];

DIMOUSESTATE m_MouseState;

int m_MouseXPos, m_MouseYPos;

LPDIRECTINPUT8 m_lpdi; // direct input object
LPDIRECTINPUTDEVICE8 m_lpdikey;
LPDIRECTINPUTDEVICE8 m_lpdimouse;

public:
TOutpost_Input();
~TOutpost_Input();

bool DI_Init(HINSTANCE, HWND);
void DI_End();

bool KeyDown(int n);

int MouseXPos();
int MouseYPos();
bool MouseDown(int);

bool UpdateKeyboard();
bool UpdateMouse(int, int, HWND, bool Windowed = false);
};

#include "OutpostI.cpp"

#endif



I don't know how to do code blocks. But this is my code.

Share this post


Link to post
Share on other sites
Zeraan    317
Quote:
Original post by Xai


please post a post with a little tree showing what files are including what ...


Ok, I should have done that. Sigh... ok here it is:

Engine, aka the Outpost:
Outpost.h - includes OutpostG.h and OutpostI.h
OutpostG.h - includes Outpost.h, TParticle.h and OutpostG.cpp.
OutpostI.h - includes Outpost.h and OutpostI.cpp
TParticle.h - includes OutpostG.h and TParticle.cpp

each of the .cpp files includes their own .h file, not Outpost.h

The game:
GameMain.h - includes Outpost.h
WinMain.cpp - includes GameMain.h
GameInit.cpp - includes GameMain.h

The Outpost files aren't included in the workspace, they're external dependences.

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by Zeraan
Ok, I should have done that. Sigh... ok here it is:

Engine, aka the Outpost:
Outpost.h - includes OutpostG.h and OutpostI.h
OutpostG.h - includes Outpost.h, TParticle.h and OutpostG.cpp.
OutpostI.h - includes Outpost.h and OutpostI.cpp
TParticle.h - includes OutpostG.h and TParticle.cpp


Bad! Don't include the .cpp from the header. The definitions are needed (from .h) for the declarations (.cpp), but NOT the other way around. Include guards protect you from multiple inclusion *within* a compilation unit; they can't protect you from multiple definitions between units (i.e. one in each unit).

Here, what happens is:

- Compiling Outpost.cpp: OutpostG.h gets included. This attempts to include Outpost.h (skipped by include guard), then TParticle.h. TParticle.h tries to include OutpostG.h (skipped by include guard) and TParticle.cpp - at this point, all the definitions of TParticle stuff get added to this compilation unit. Then OutpostG.h includes OutpostG.cpp, which brings in those definitions as well. Finally, the Outpost stuff itself is present in that unit.

- Compiling OutpostG.h: Similarly, you get TParticle in here. Actually, this only even *compiles* because you presumably have an include guard on the .cpp file as well.

- etc.

- Finally we get to linking, and the linker gives up, because these four .o files it's been given - Outpost.o, OutpostG.o, etc. have multiple definitions of TParticle stuff (and other stuff too) between them. They're actually not necessarily even identical (because of compiler optimizations), and even if they were, the linker would not be able to accept it - it's trying to match up all the calls to TParticle functions to implementations of said functions, and for any given call, there are multiple choices - this violates the so-called "One Definition Rule".

In short: Don't include .cpp files! Oh, and read this already.. :)


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this