Page 1 of 2

Needed help with spliting up code

Posted: Mon Mar 23, 2009 1:51 pm
by Norbo
I have a code and i wanted to split it up but i didint know how to.
So i read the lazyfoo's article on splitting source files.
I did everything right, but i have a problem with my functions.
When i compile my main.cpp file, i have tons of errors, all saying 2 things:

' warning: <myVarName> initialized and declared `extern'
Where myVarName is the name of the variable
It says that for all my vars

and:

main.cpp: undefined reference to <myFunctionName>
Where myFunctionName is the name of the function
It says that for all my functions

I must be doing something wrong, but what? This is my functions.h:

Code: Select all

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

//The headers
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_mixer.h"
#include "SDL/SDL_ttf.h"
#include <string>

int play_sound(Mix_Chunk *var1,Mix_Music *var2);

void log(std::string error);

SDL_Surface *load_image( std::string filename);

void draw_image(int x,int y,SDL_Surface *source,SDL_Surface *destination);

void handleMenuInput();

void initButtons();

void clean_up();

bool initMusic();

bool init();

void showButtons();

#endif
and this is my functions.cpp:

Code: Select all

#include "functions.h"
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h
#include "SDL/SDL_mixer.h"
#include <string>
#include "vars.h"

SDL_Surface *load_image( std::string filename)
{ 
    //The image that's loaded 
    SDL_Surface* loadedImage = NULL; 
    //The optimized image that will be used 
    SDL_Surface* optimizedImage = NULL; 
    //Load the image using SDL_image 
    loadedImage = IMG_Load( filename.c_str() ); 
    //If the image loaded 
    if( loadedImage != NULL ) 
    { 
        //Create an optimized image 
        optimizedImage = SDL_DisplayFormat( loadedImage ); 
        //Free the old image 
        SDL_FreeSurface( loadedImage ); 
        //If the image was optimized just fine
        if( optimizedImage != NULL )
        {
            if (filename != "graphics/space.png" && filename != "graphics/spaceship.png")
            {
                //Map the color key
                Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 255, 255, 255 );
                //Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent
                SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
            }
        }
    }
    //Return the optimized image 
    return optimizedImage; 
} 

void draw_image(int x,int y,SDL_Surface *source,SDL_Surface *destination)
{
    //Make a temporary rectangle to hold the offsets 
    SDL_Rect offset; 
    
    //Give the offsets to the rectangle 
    offset.x = x; 
    offset.y = y; 
        
    SDL_BlitSurface(source,NULL,destination,&offset);
}

int play_sound(Mix_Chunk *var1,Mix_Music *var2)
{
    //Play the scratch effect
    if (var1 != NULL && var2 == NULL)
    {
        if( Mix_PlayChannel( -1, var1, 0 ) == -1 ) {
            return 1;    
        }
    }
    if (var1 == NULL && var2 != NULL)
    {
        Mix_HaltMusic();
        //Play the music
        if( Mix_PlayMusic(var2, -1 ) == -1 ) {
            return 1;
        }    
    }   
}

#undef showButtons
void showButtons()
{
    play.show();
    howto.show();
    options.show();
    credits.show();
    ok.show();
    exit1.show();
    back.show();
}

void startGame()
{
    mainMenu = false;
    inGame = true;
    player.ship();
}

void handleMenuInput()
{
    //While there's an event to handle 
    while(SDL_PollEvent(&event)) 
    { 
        //If a key was pressed
        if( event.type == SDL_KEYDOWN )
        {
            if (currentButton>0 && currentButton<=7)
            {
                switch( event.key.keysym.sym )
                {
                    case SDLK_UP: 
                        currentButton--; 
                        play_sound(peep.sfx,NULL);
                        break;
                    case SDLK_DOWN: 
                        currentButton++; 
                        play_sound(peep.sfx,NULL); 
                        break;
                    case SDLK_RETURN:
                        if (currentButton == 5)
                        {
                            quit = true;
                        }
                        if (currentButton == 1)
                        {
                            startGame();
                        }
                }
            }
        }
    }
}

void initButtons()
{
    log("init buttons");
    play.id = 1;
    howto.id = 2;
    options.id = 3;
    credits.id = 4;
    exit1.id = 5;
    ok.id = 6;
    back.id = 7;
    play.offset.x = 404;
    play.offset.y = 100;
    howto.offset.x = 404;
    howto.offset.y = 200;
    options.offset.x = 404;
    options.offset.y = 300;
    credits.offset.x = 404;
    credits.offset.y = 400;    
    exit1.offset.x = 404;
    exit1.offset.y = 500;
    ok.offset.x = 404;
    ok.offset.y = 600;
    back.offset.x = 404;
    back.offset.y = 700;
    back.imageOver = load_image("graphics/back_mouseover.png");
    if (back.imageOver == NULL)
    {
        log(IMG_GetError());
    }
    back.imageUp = load_image("graphics/back_up.png");
    if (back.imageUp == NULL)
    {
        log(IMG_GetError());
    }
    credits.imageOver = load_image("graphics/credits_mouseover.png");
    if (credits.imageOver == NULL)
    {
        log(IMG_GetError());
    }
    credits.imageUp = load_image("graphics/credits_up.png");
    if (credits.imageUp == NULL)
    {
        log(IMG_GetError());
    }
    exit1.imageOver = load_image("graphics/exit_mouseover.png");
    if (exit1.imageOver == NULL)
    {
        log(IMG_GetError());
    }
    exit1.imageUp = load_image("graphics/exit_up.png");
    if (exit1.imageUp == NULL)
    {
        log(IMG_GetError());
    }
    howto.imageOver = load_image("graphics/howto_mouseover.png");
    if (howto.imageOver == NULL)
    {
        log(IMG_GetError());
    }
    howto.imageUp = load_image("graphics/howto_up.png");
    if (howto.imageUp == NULL)
    {
        log(IMG_GetError());
    }
    ok.imageOver = load_image("graphics/ok_button mouse_over.png");
    if (ok.imageOver == NULL)
    {
        log(IMG_GetError());
    }
    ok.imageUp = load_image("graphics/ok_button_up.png");
    if (ok.imageUp == NULL)
    {
        log(IMG_GetError());
    }
    play.imageOver = load_image("graphics/playgame_mouseover.png");
    if (play.imageOver == NULL)
    {
        log(IMG_GetError());
    }
    play.imageUp = load_image("graphics/playgame_up.png");
    if (play.imageUp == NULL)
    {
        log(IMG_GetError());
    }
}

void clean_up() 
{ 
    //Free the sound effects
    Mix_FreeChunk(peep.sfx);
    //Quit SDL_mixer
    Mix_CloseAudio();
    //Quit SDL_ttf
    TTF_Quit();    
    //Quit SDL 
    SDL_Quit(); 
} 

bool initMusic()
{

    menu.sound = Mix_LoadMUS("sounds/menu.wav");
    if(menu.sound == NULL )
    {
        log(Mix_GetError());
        return false;    
    }
    game.sound = Mix_LoadMUS("sounds/game.wav");
    if(game.sound == NULL )
    {
        log(Mix_GetError());
        return false;    
    }
    peep.sfx = Mix_LoadWAV("sounds/peep.wav");
    return true;
}

bool init()
{
    //Initialize all SDL subsystems 
    if(SDL_Init(SDL_INIT_EVERYTHING)==-1) { 
        return false; 
    } 
    //Initialize SDL_ttf
    if( TTF_Init() == -1 )
    {
        return false;    
    }
    //Initialize SDL_mixer
    if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 )
    {
        return false;    
    }
    player.image = load_image("graphics/spaceship.png");
    if (player.image == NULL)
    {
        log(IMG_GetError());
    }
    bg = load_image("graphics/space.png");
    gameOverImage = load_image("graphics/gameover.png");
    return true;
}
Whats wrong? Please help me.
Thanks.

Re: Needed help with spliting up code

Posted: Mon Mar 23, 2009 1:57 pm
by avansc
well tel us whats the error. i mean we cant just look at that and compile it in out heads. and we certainly arent gonna compile and fix it for you.

i once had a C class in college were the tests were like here is code, what error will the compiler give if any.. YUK

Re: Needed help with spliting up code

Posted: Mon Mar 23, 2009 2:07 pm
by Norbo
but i have posted the errors...
Norbo wrote: When i compile my main.cpp file, i have tons of errors, all saying 2 things:

' warning: <myVarName> initialized and declared `extern'
Where myVarName is the name of the variable
It says that for all my vars

and:

main.cpp: undefined reference to <myFunctionName>
Where myFunctionName is the name of the function
It says that for all my functions

Re: Needed help with spliting up code

Posted: Mon Mar 23, 2009 2:50 pm
by programmerinprogress
how do you add these things into your main.cpp?

if you are using anything from those header files, you need to make sure you include them into main too.

i.e. you need to #include "functions.h" if your calling these in your code.

Re: Needed help with spliting up code

Posted: Mon Mar 23, 2009 3:52 pm
by Norbo
yes, i am including everything

Re: Needed help with spliting up code

Posted: Mon Mar 23, 2009 5:25 pm
by PixelP
you must do "extern" before every function in the header file. like:

Code: Select all

//functions.h
extern bool init();

Code: Select all

//functions.cpp
bool init()
{
//code
}

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 2:08 am
by Norbo
PixelP wrote:you must do "extern" before every function in the header file. like:

Code: Select all

//functions.h
extern bool init();

Code: Select all

//functions.cpp
bool init()
{
//code
}
hmm okay i will try and post if it works here. thanks

EDIT: NOPE, DOSENT WORK :(

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 6:35 am
by rolland
PixelP wrote:you must do "extern" before every function in the header file.
I thought functions were 'extern' by default.
Anyway, the only thing I can think of is to make sure those files are included in your main project. All of the undefined reference errors lead me to believe that the cpp file isn't being linked.
Then again, I'm a n00b. I might be horribly wrong.

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 8:57 am
by MarauderIIC
PixelP wrote:you must do "extern" before every function in the header file.
False. I've never seen it done this way and assume bad practice.
rolland wrote:make sure those files are ...in your main project.
Agree. Did you "add new/existing file" them?

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 10:41 am
by Norbo
MarauderIIC wrote:
PixelP wrote:you must do "extern" before every function in the header file.
False. I've never seen it done this way and assume bad practice.
rolland wrote:make sure those files are ...in your main project.
Agree. Did you "add new/existing file" them?
I never knew i had to add my files to the current project! Thanks so much, no more undefined reference errors. However i still have my ' warning: <myVarName> initialized and declared `extern' errors. Any ideas on how to get rid of em?

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 1:31 pm
by sparda
Norbo, what compiler are you using anyway? You do understand that there are no external variables declared or defined in the files you provided, meaning we won't be able to see the full problem unless you let us see the entire source (good luck to you pedantic people :lol: ).

BTW, you're getting extern "warnings" not errors; although I wouldn't be surprised if those are the cause of your problems. My motto is, if you don't understand it, don't use it until you do. One thing that people usually mix up is the concept of declaring and defining. If you're declaring variables extern somewhere in you source, you must define them as well. The details of this are very specific. By declaring an external variable you are merely instructing the compiler to not allocate any memory for it, among other things.

By default identifiers are put on the symbol table of a specific translation unit, so by declaring a variable extern, other translations units can access it by name (i.e. other implementation files or .cpps, etc). Think of it as function prototypes and their respective definitions. Also, external variable are global, you understand that right? Remember, extern variables are handled by the linker. You must understand linkage as defined by the ANSI standard if you want to do anything of the sort, so hit the books.

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 2:17 pm
by Norbo
Im using Dev-C++ as my IDE
this is my globals.h

Code: Select all

#ifndef GLOBALS_H
#define GLOBALS_H

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <fstream>

extern SDL_Surface *screen = NULL;
extern SDL_Event event;
extern SDL_Surface *bg = NULL;
extern SDL_Surface *gameOverImage = NULL;
extern int currentButton = 1;
extern //Get the keystates 
extern bool mainMenu = true;
extern bool quit = false;
extern bool inGame = false;

//File stream for the game log. 
extern std::ofstream logger( "log.txt" ); 

#endif
and this is my globals.cpp

Code: Select all

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_mixer.h"
#include <fstream>
#include "globals.h"

SDL_Surface *screen = NULL;
SDL_Event event;
SDL_Surface *bg = NULL;
SDL_Surface *gameOverImage = NULL;
int currentButton = 1;
//Get the keystates 
bool mainMenu = true;
bool quit = false;
bool inGame = false;

//File stream for the game log. 
std::ofstream logger( "log.txt" ); 
im linking everything in my main.cpp
my compile log is:

Code: Select all

Compiler: Default compiler
Building Makefile: "C:\Dev-Cpp\sda\Makefile.win"
Executing  make...
make.exe -f "C:\Dev-Cpp\sda\Makefile.win" all
g++.exe -c globals.cpp -o globals.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include"  -I"C:/SDL-1.2.13/include"  -I"C:/Dev-Cpp/include"  -I"C:/Dev-Cpp/include/c++"  -I"C:/SDL-1.2.13/include"   

In file included from globals.cpp:6:
globals.h:8: warning: `screen' initialized and declared `extern'
globals.h:10: warning: `bg' initialized and declared `extern'
globals.h:11: warning: `gameOverImage' initialized and declared `extern'
globals.h:12: warning: `currentButton' initialized and declared `extern'
globals.h:14: error: duplicate `extern'
globals.h:14: warning: `mainMenu' initialized and declared `extern'
globals.h:15: warning: `quit' initialized and declared `extern'
globals.h:16: warning: `inGame' initialized and declared `extern'
globals.h:19: warning: `logger' initialized and declared `extern'

globals.cpp:8: error: redefinition of `SDL_Surface*screen'
globals.h:8: error: `SDL_Surface*screen' previously defined here
globals.cpp:10: error: redefinition of `SDL_Surface*bg'
globals.h:10: error: `SDL_Surface*bg' previously defined here
globals.cpp:11: error: redefinition of `SDL_Surface*gameOverImage'
globals.h:11: error: `SDL_Surface*gameOverImage' previously defined here
globals.cpp:12: error: redefinition of `int currentButton'

globals.h:12: error: `int currentButton' previously defined here
globals.cpp:14: error: redefinition of `bool mainMenu'
globals.h:14: error: `bool mainMenu' previously defined here
globals.cpp:15: error: redefinition of `bool quit'
globals.h:15: error: `bool quit' previously defined here
globals.cpp:16: error: redefinition of `bool inGame'
globals.h:16: error: `bool inGame' previously defined here
globals.cpp:19: error: redefinition of `std::ofstream logger'
globals.h:19: error: `std::ofstream logger' previously declared here

make.exe: *** [globals.o] Error 1

Execution terminated
Now, my question is, why do i get these errors, when im linking declaring and defining everything right?
Do you understand me now? I just want to fix these errors.

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 2:23 pm
by MarauderIIC
Remove your initializations from the "extern" lines. IE, remove the = from the part that says "extern". Notice, you're initializing them twice?

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 2:23 pm
by sparda
Dude, you're trying to define and declare at the same time in your globals.h.

Remove the assignment operator, and just declare your externs first. Like this (global.h)

Code: Select all


extern SDL_Surface *screen;
extern SDL_Event event;
extern SDL_Surface *bg;
extern SDL_Surface *gameOverImage;
extern int currentButton;
extern //Get the keystates
extern bool mainMenu;
extern bool quit;
extern bool inGame;
extern std::ofstream logger; 
That should eliminate your extern problem.

Re: Needed help with spliting up code

Posted: Tue Mar 24, 2009 3:41 pm
by Norbo
Wow, that was foolish of me..
Thank you.
But now i have multiple definitions errors... :evil: