Needed help with spliting up code

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Norbo
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 15
Joined: Thu Mar 19, 2009 11:58 am

Needed help with spliting up code

Post 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.
Last edited by Norbo on Mon Mar 23, 2009 2:07 pm, edited 1 time in total.
User avatar
avansc
Respected Programmer
Respected Programmer
Posts: 1708
Joined: Sun Nov 02, 2008 6:29 pm

Re: Needed help with spliting up code

Post 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
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Norbo
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 15
Joined: Thu Mar 19, 2009 11:58 am

Re: Needed help with spliting up code

Post 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
User avatar
programmerinprogress
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 632
Joined: Wed Oct 29, 2008 7:31 am
Current Project: some crazy stuff, i'll tell soon :-)
Favorite Gaming Platforms: PC
Programming Language of Choice: C++!
Location: The UK
Contact:

Re: Needed help with spliting up code

Post 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.
---------------------------------------------------------------------------------------
I think I can program pretty well, it's my compiler that needs convincing!
---------------------------------------------------------------------------------------
And now a joke to lighten to mood :D

I wander what programming language anakin skywalker used to program C3-PO's AI back on tatooine? my guess is Jawa :P
Norbo
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 15
Joined: Thu Mar 19, 2009 11:58 am

Re: Needed help with spliting up code

Post by Norbo »

yes, i am including everything
User avatar
PixelP
Chaos Rift Regular
Chaos Rift Regular
Posts: 153
Joined: Tue Oct 07, 2008 12:23 pm
Programming Language of Choice: c/c++
Location: sweden
Contact:

Re: Needed help with spliting up code

Post 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
}
Norbo
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 15
Joined: Thu Mar 19, 2009 11:58 am

Re: Needed help with spliting up code

Post 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 :(
User avatar
rolland
Chaos Rift Regular
Chaos Rift Regular
Posts: 127
Joined: Fri Dec 21, 2007 2:27 pm
Current Project: Starting an Android app soon
Favorite Gaming Platforms: PS1, N64
Programming Language of Choice: C++
Location: Michigan, US

Re: Needed help with spliting up code

Post 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.
I'll write a signature once I get some creativity and inspiration...
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Re: Needed help with spliting up code

Post 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?
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
Norbo
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 15
Joined: Thu Mar 19, 2009 11:58 am

Re: Needed help with spliting up code

Post 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?
User avatar
sparda
Chaos Rift Junior
Chaos Rift Junior
Posts: 291
Joined: Tue Sep 23, 2008 3:54 pm

Re: Needed help with spliting up code

Post 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.
Norbo
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 15
Joined: Thu Mar 19, 2009 11:58 am

Re: Needed help with spliting up code

Post 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.
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Re: Needed help with spliting up code

Post by MarauderIIC »

Remove your initializations from the "extern" lines. IE, remove the = from the part that says "extern". Notice, you're initializing them twice?
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
User avatar
sparda
Chaos Rift Junior
Chaos Rift Junior
Posts: 291
Joined: Tue Sep 23, 2008 3:54 pm

Re: Needed help with spliting up code

Post 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.
Norbo
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 15
Joined: Thu Mar 19, 2009 11:58 am

Re: Needed help with spliting up code

Post by Norbo »

Wow, that was foolish of me..
Thank you.
But now i have multiple definitions errors... :evil:
Post Reply