   Linker error involving #includes  (I know the problem just don't know why)
  I'm making a pong clone using C++ and the windows api.  I'm using Visual Studio 2008 Professional Ed.  At the moment, my code is all in one source file.  It works fine there but I don't want everything in one source file and want to seperate the game specific stuff from the windows stuff.  I tried to do this as follows:Game.cpp#include "Game.h"void NewGame(){}void GameInit(){g_Ball.x = (SCREEN_WIDTH / 2);g_Ball.y = (SCREEN_HEIGHT / 2);g_Ball.w = 32;g_Ball.h = 32;g_Ball.dx = BALL_MOVE_DELTA;g_Ball.dy = BALL_MOVE_DELTA;g_RedPaddle.x = 100;g_RedPaddle.y = (SCREEN_HEIGHT / 2) - 64;g_RedPaddle.w = 32;g_RedPaddle.h = 64;g_BluePaddle.x = SCREEN_WIDTH - 100;g_BluePaddle.y = (SCREEN_HEIGHT / 2) - 64;g_BluePaddle.w = 32;g_BluePaddle.h = 64;}void GameMain(){}void GameQuit(){}void Draw(){}Game.h#ifndef GAME_H#define GAME_H#include <windows.h>#define W 0x57#define S 0x53#define P 0x50const char g_szClassName[] = "Pong";const int ID_TIMER = 1;const int SCREEN_WIDTH = 1024;const int SCREEN_HEIGHT = 700;const int BALL_MOVE_DELTA = 7;const int PADDLE_MOVE_DELTA = 5;typedef struct _OBJECT {int w;int h;int x;int y;int dx;int dy;}OBJECT;OBJECT g_Ball;OBJECT g_RedPaddle;OBJECT g_BluePaddle;HBITMAP g_hbmBall = NULL;HBITMAP g_hbmRedPaddle = NULL;HBITMAP g_hbmBluePaddle = NULL;int g_iScoreLimit;bool g_bPause = false;bool g_bMoveUp[2];//flags for moving paddles up 0 left pad 1 right padbool g_bMoveDown[2];//flags for moving paddles down 0 left pad 1 right padbool g_bBallMove;//flag for moving ballvoid NewGame();void Draw();void GameInit();void GameMain();void GameQuit();#endifwinmain.cpp#include <windows.h>#include "resource.h"#include "Game.h"void Draw(HDC hdc, RECT* prc){HDC hdcBuffer = CreateCompatibleDC(hdc);HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);HBITMAP hbmOldBuffer = (HBITMAP)SelectObject(hdcBuffer, hbmBuffer);HDC hdcMem = CreateCompatibleDC(hdc);HBITMAP hbmOld = NULL;FillRect(hdcBuffer, prc, (HBRUSH)GetStockObject(BLACK_BRUSH));BitBlt(hdcBuffer, g_Ball.x, g_Ball.y, g_Ball.w, g_Ball.h, hdcMem, 0, 0, SRCAND);SelectObject(hdcMem, g_hbmBall);BitBlt(hdcBuffer, g_Ball.x, g_Ball.y, g_Ball.w, g_Ball.h, hdcMem, 0, 0, SRCPAINT);SelectObject(hdcMem, g_hbmRedPaddle);BitBlt(hdcBuffer, g_RedPaddle.x, g_RedPaddle.y, g_RedPaddle.w, g_RedPaddle.h, hdcMem, 0, 0, SRCPAINT);SelectObject(hdcMem, g_hbmBluePaddle);BitBlt(hdcBuffer, g_BluePaddle.x, g_BluePaddle.y, g_BluePaddle.w, g_BluePaddle.h, hdcMem, 0, 0, SRCPAINT);BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);SelectObject(hdcMem, hbmOld);DeleteDC(hdcMem);SelectObject(hdcBuffer, hbmOldBuffer);DeleteDC(hdcBuffer);DeleteObject(hbmBuffer);}void UpdateBall(RECT* prc){g_Ball.x += g_Ball.dx;g_Ball.y += g_Ball.dy;if(g_Ball.x < 0){g_Ball.x = 0;g_Ball.dx = BALL_MOVE_DELTA;}else if(g_Ball.x + g_Ball.w > prc->right){g_Ball.x = prc->right - g_Ball.w;g_Ball.dx = -BALL_MOVE_DELTA;}if(g_Ball.y < 0){g_Ball.y = 0;g_Ball.dy = BALL_MOVE_DELTA;}else if(g_Ball.y + g_Ball.h > prc->bottom){g_Ball.y = prc->bottom - g_Ball.h;g_Ball.dy = -BALL_MOVE_DELTA;}}// the Dialog window procedureBOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam){switch(Message){case WM_INITDIALOG:return TRUE;case WM_COMMAND:switch(LOWORD(wParam)){case IDOK:EndDialog(hwnd, IDOK);break;}break;default:return FALSE;}return TRUE;}//end of dialog proc// Step 4: the Window ProcedureLRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){static int iSelection = ID_GAMEPOINT_10;    switch(msg)    {case WM_CREATE:UINT ret;ret = SetTimer(hwnd, ID_TIMER, 50, NULL);if(ret == 0)MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));if(g_hbmBall == NULL)MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);g_hbmRedPaddle = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_REDPADDLE));if(g_hbmRedPaddle == NULL)MessageBox(hwnd, "Could not load IDB_REDPADDLE!", "Error", MB_OK | MB_ICONEXCLAMATION);g_hbmBluePaddle = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BLUEPADDLE));if(g_hbmBluePaddle == NULL)MessageBox(hwnd, "Could not load IDB_REDPADDLE!", "Error", MB_OK | MB_ICONEXCLAMATION);GameInit();break;case WM_COMMAND:HMENU hMenu;hMenu = GetMenu(hwnd);switch(LOWORD(wParam)){case ID_FILE_NEWGAME:NewGame();break;case ID_FILE_PAUSE:(g_bPause==true) ? (g_bPause=false) : (g_bPause=true);  //Pause game if unpaused, unpause if pausedbreak;case ID_FILE_EXIT:PostMessage(hwnd, WM_CLOSE, 0, 0);break;case ID_GAMEPOINT_5:{CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);iSelection = LOWORD (wParam);CheckMenuItem(hMenu, iSelection, MF_CHECKED);if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)g_iScoreLimit = 5;}break;case ID_GAMEPOINT_10:{CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);iSelection = LOWORD (wParam);CheckMenuItem(hMenu, iSelection, MF_CHECKED);if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)g_iScoreLimit = 10;}break;case ID_GAMEPOINT_15:{CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);iSelection = LOWORD (wParam);CheckMenuItem(hMenu, iSelection, MF_CHECKED);if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)g_iScoreLimit = 15;}break;case ID_GAMEPOINT_20:{CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);iSelection = LOWORD (wParam);CheckMenuItem(hMenu, iSelection, MF_CHECKED);if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)g_iScoreLimit = 20;}break;case ID_HELP_HOWTOPLAY:DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_HOWTOPLAY), hwnd, AboutDlgProc);break;case ID_HELP_ABOUT:MessageBox(hwnd,"Pong Game created by SonicD007", "About", MB_OK | MB_ICONINFORMATION);break;} break;case WM_KEYDOWN:switch(wParam){case W:g_bMoveUp[0] = true;break;//this is where the boolean var would go to move upcase S:g_bMoveDown[0] = true;break;//this is where the boolean var would go to move downcase VK_UP:g_bMoveUp[1] = true;break;//this is where the boolean var would go to move upcase VK_DOWN:g_bMoveDown[1] = true;break;//this is where the boolean var would go to move downcase VK_SPACE:g_bBallMove = true;break;case P:(g_bPause==true) ? (g_bPause=false) : (g_bPause=true);break;}break;case WM_KEYUP:switch(wParam){case W:g_bMoveUp[0] = false;break;//this is where the boolean var would go to move upcase S:g_bMoveDown[0] = false;break;//this is where the boolean var would go to move downcase VK_UP:g_bMoveUp[1] = false;break;//this is where the boolean var would go to move upcase VK_DOWN:g_bMoveDown[1] = false;break;//this is where the boolean var would go to move down}break;case WM_PAINT:{RECT rcClient;PAINTSTRUCT ps;HDC hdc = BeginPaint(hwnd, &ps);GetClientRect(hwnd, &rcClient);Draw(hdc, &rcClient);EndPaint(hwnd, &ps);}break;case WM_TIMER:{RECT rcClient;HDC hdc = GetDC(hwnd);GetClientRect(hwnd, &rcClient);UpdateBall(&rcClient);Draw(hdc, &rcClient);ReleaseDC(hwnd, hdc);}break;   case WM_CLOSE:  DestroyWindow(hwnd);break;/*case WM_NCCALCSIZE:break;   //this is where we need to stop the window from being resized */case WM_DESTROY:{KillTimer(hwnd, ID_TIMER);GameQuit();DeleteObject(g_hbmBall);DeleteObject(g_hbmRedPaddle);DeleteObject(g_hbmBluePaddle);PostQuitMessage(0);}break;   default:  return DefWindowProc(hwnd, msg, wParam, lParam);    }    return 0;}//end of wind procint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,    LPSTR lpCmdLine, int nCmdShow){    WNDCLASSEX wc;    HWND hwnd;    MSG Msg;    //Step 1: Registering the Window Class    wc.cbSize   = sizeof(WNDCLASSEX);    wc.style    = 0;    wc.lpfnWndProc   = WndProc;    wc.cbClsExtra    = 0;    wc.cbWndExtra    = 0;    wc.hInstance= hInstance;    wc.hIcon    = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_APPICON));    wc.hCursor  = LoadCursor(NULL, IDC_ARROW);    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);//+3 gives black +1 gives white    wc.lpszMenuName  = MAKEINTRESOURCE(IDM_MENU1);    wc.lpszClassName = g_szClassName;    wc.hIconSm  = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_APPICON));    if(!RegisterClassEx(&wc))    {   MessageBox(NULL, "Window Registration Failed!", "Error!",  MB_ICONEXCLAMATION | MB_OK);   return 0;    }    // Step 2: Creating the Window    hwnd = CreateWindowEx(   WS_EX_CLIENTEDGE,   g_szClassName,   "Pong",   WS_OVERLAPPEDWINDOW,   CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH, SCREEN_HEIGHT,   NULL, NULL, hInstance, NULL);    if(hwnd == NULL)    {   MessageBox(NULL, "Window Creation Failed!", "Error!",  MB_ICONEXCLAMATION | MB_OK);   return 0;    }    ShowWindow(hwnd, SW_SHOWMAXIMIZED);    UpdateWindow(hwnd);    // Step 3: The Message Loopwhile(GetMessage(&Msg, NULL, 0, 0) > 0){TranslateMessage(&Msg);DispatchMessage(&Msg);GameMain();}return Msg.wParam;}//end of win mainThe errors I get is:Error12fatal error LNK1169: one or more multiply defined symbols foundC:\Users\Daniel Caban\Documents\Visual Studio 2008\Projects\winmain\Debug\winmain.exeError9error LNK2005: "struct HBITMAP__ * g_hbmRedPaddle" (?g_hbmRedPaddle@@3PAUHBITMAP__@@A) already defined in Game.objwinmain.objError10error LNK2005: "struct HBITMAP__ * g_hbmBluePaddle" (?g_hbmBluePaddle@@3PAUHBITMAP__@@A) already defined in Game.objwinmain.objError8error LNK2005: "struct HBITMAP__ * g_hbmBall" (?g_hbmBall@@3PAUHBITMAP__@@A) already defined in Game.objwinmain.objError3error LNK2005: "struct _OBJECT g_RedPaddle" (?g_RedPaddle@@3U_OBJECT@@A) already defined in Game.objwinmain.objError2error LNK2005: "struct _OBJECT g_BluePaddle" (?g_BluePaddle@@3U_OBJECT@@A) already defined in Game.objwinmain.objError5error LNK2005: "struct _OBJECT g_Ball" (?g_Ball@@3U_OBJECT@@A) already defined in Game.objwinmain.objError4error LNK2005: "int g_iScoreLimit" (?g_iScoreLimit@@3HA) already defined in Game.objwinmain.objError11error LNK2005: "bool g_bPause" (?g_bPause@@3_NA) already defined in Game.objwinmain.objError6error LNK2005: "bool g_bBallMove" (?g_bBallMove@@3_NA) already defined in Game.objwinmain.objError1error LNK2005: "bool * g_bMoveUp" (?g_bMoveUp@@3PA_NA) already defined in Game.objwinmain.objError7error LNK2005: "bool * g_bMoveDown" (?g_bMoveDown@@3PA_NA) already defined in Game.objwinmain.objIf I delete the #include "Game.h" from Game.cpp, it complains about things not being defined.  I thought the header guards in Game.h would prevent any redefinitions but doesn't look like it's doing its job.  This code works fine if I put it back into winmain.cpp (aside from the void GameInit() ect.)Any ideas why it's doing this?   
  Basically you can't define variables in headers like you did there and then include that header into multiple .cpp files.  Each .cpp is compiled separately.  This means that all the variables in the header get built in to each .cpp that includes them.  The linker takes all the separately generated object files and "links" them together.  Because of the separate compiler segments deal, you end up with variables with the same name declared in every compiler segment.The c-solution to this is to put the word "extern" before all those variable declarations and to move the assignments into a single .cpp file.extern const char g_szClassName[];extern const int ID_TIMER;then in only one of the .cpp filesconst char g_szClassName[] = "Pong";const int ID_TIMER = 1;-me   ;  Thanks for the help.  Also, if instead I moved this stuff from Game.h into winmain.h and got rid of Game.h and Game.cpp completely, that would solve the problem too correct? ;Quote:Original post by SonicD007Thanks for the help.  Also, if instead I moved this stuff from Game.h into winmain.h and got rid of Game.h and Game.cpp completely, that would solve the problem too correct?It's very bad practice to declare non-extern variables in the header files for the reasons I posted.  Some day down the road you may want/need that header included elsewhere.  May as well do it "right" from the get go-me   ;  Okay, I started putting extern in front of the variables in my header file but I'm not sure what I do with the OBJECT struct I have.  If I put:extern OBJECT g_Ball.x = (SCREEN_WIDTH / 2);I get an error message saying:Error1error C2146: syntax error : missing ';' before identifier 'g_Ball'c:\users\daniel caban\documents\visual studio 2008\projects\winmain\winmain\game.cpp10I don't see any errors with ; ( ) { } so what am I doing wrong??  I left the OBJECT struct in Game.h unchanged.Sorry for the hassle, this is the first time I use the extern keyword and I looked it up to try to figure out what was happening but I'm clueless :/  I understand extern says the variable is declared in another file, but why won't the same "steps" work with the struct?   ;  You are trying to initialize a declaration. You should only initialize the definition. So it should just be, in the header:extern OBJECT g_Ball;And in one source file you would need to use struct initialization syntax like this:OBJECT g_Ball = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, WHATEVER_X, WHATEVER_Y, DELTA_X, DELTA_Y};I'm fairly sure you can't initialize individual struct members like that when they are global.   ;  no.  you can't assign a value to an extern in the header. And also that assignment wouldn't work anyway because you're trying to declare the variable and set a member value in the same statement with the dot syntax. Anyway, look at the example I pasted again and pay close attention to where the word "extern" is used and where values are assigned.Also you had that assignment correct to begin with in the GameInit function.  Why change it?All you need is:headerextern OBJECT gBall;.cpp fileOBJECT gBall;-me   ;  I am just not getting this :/  The regular variables seem like they're fine now.  This is what my code looks like now:Game.h#ifndef GAME_H#define GAME_H#include <windows.h>#define W 0x57#define S 0x53#define P 0x50  extern const int BALL_MOVE_DELTA; extern const int PADDLE_MOVE_DELTA; extern const int SCREEN_WIDTH; extern const int SCREEN_HEIGHT; typedef struct _OBJECT {int w;int h;int x;int y;int dx;int dy;}OBJECT;  extern OBJECT g_Ball;  extern OBJECT g_RedPaddle;  extern OBJECT g_BluePaddle; HBITMAP g_hbmBall = NULL; HBITMAP g_hbmRedPaddle = NULL; HBITMAP g_hbmBluePaddle = NULL; extern int g_iScoreLimit; extern bool g_bPause; extern bool g_bMoveUp[2];//flags for moving paddles up 0 left pad 1 right pad extern bool g_bMoveDown[2];//flags for moving paddles down 0 left pad 1 right pad extern bool g_bBallMove;//flag for moving ballvoid NewGame();void Draw();void GameInit();void GameMain();void GameQuit();#endifGame.cppconst int BALL_MOVE_DELTA = 7;const int PADDLE_MOVE_DELTA = 5;const int SCREEN_WIDTH = 1024;const int SCREEN_HEIGHT = 700;void NewGame(){}void GameInit(){int g_iScoreLimit = 10;bool g_bPause = false;OBJECT g_Ball = {(SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2), 32, 32, BALL_MOVE_DELTA, BALL_MOVE_DELTA}; /*g_RedPaddle.x = 100; g_RedPaddle.y = (SCREEN_HEIGHT / 2) - 64; g_RedPaddle.w = 32; g_RedPaddle.h = 64; g_BluePaddle.x = SCREEN_WIDTH - 100; g_BluePaddle.y = (SCREEN_HEIGHT / 2) - 64; g_BluePaddle.w = 32; g_BluePaddle.h = 64;*/}void GameMain(){}void GameQuit(){}void Draw(){}The errors :(Error2error C2146: syntax error : missing ';' before identifier 'g_Ball'c:\users\daniel caban\documents\visual studio 2008\projects\winmain\winmain\game.cpp19Error6error C2143: syntax error : missing ';' before '}'c:\users\daniel caban\documents\visual studio 2008\projects\winmain\winmain\game.cpp19Error5error C2143: syntax error : missing ';' before '{'c:\users\daniel caban\documents\visual studio 2008\projects\winmain\winmain\game.cpp19Error1error C2065: 'OBJECT' : undeclared identifierc:\users\daniel caban\documents\visual studio 2008\projects\winmain\winmain\game.cpp19Error3error C2065: 'g_Ball' : undeclared identifierc:\users\daniel caban\documents\visual studio 2008\projects\winmain\winmain\game.cpp19Error4error C2059: syntax error : '{'c:\users\daniel caban\documents\visual studio 2008\projects\winmain\winmain\game.cpp19Seems like everything is becoming more hectic.  Again I appreciate all the help.   ;  OBJECT is an undeclared udentifier in, like, every file except one. You need to declare OBJECT in a header file and include that header in every file that wants to use OBJECT.   ;  I have OBJECT declared in Game.h though.  If I try including Game.h to Game.cpp that brings me back to the beginning of the post with the linker errors.  Should I have a separate header file specifically for typedef struct declarations or am I overlooking something?   