Game dev
thread
Quick Fix
Full Solution
My Comments
The Problem
What does an error like this mean?
1>Particle.obj : error LNK2005: "struct SDL_Surface * red" (?red@@3PAUSDL_Surface@@A) already defined in main.obj
to put it simply it means that a global variable is
defined in two source files because you included the same header file in two different source files.
Lets say I have two source files
main.cpp and
particle.cpp and a header file called
globalobjs.h. In my header file I declare a variable of integer type. Now I need to use this number in both main.cpp and particle.cpp so I'm going to
#include "globalobs.h"
in both source files. But here is the problem, if I include that globalobjs twice it is like saying the line:
int variable;
twice and so the the linker gives an error message. It is because it doesn't know if I am talking about the same variable or two different variables. It wonders if you want the same variable used in two source files or if you want the two source files to have their own integer called variable. The same logical conclusions would apply for any other type of variable or even functions
In my case here is my Header file called particle.h:
#pragma once
#include
SDL_Surface *red;
SDL_Surface *green;
SDL_Surface *blue;
SDL_Surface *shimmer;
#ifndef PARTICLE
#define PARTICLE
class Particle
{
protected:
//offsets
int x,y;
// current frame of animation
int frame;
//type of particle
SDL_Surface* type;
public:
Particle(int X, int Y);
~Particle(void);
void show();
bool is_dead();
};
#endif
And here is one of my source files called particles.cpp:
#include "Particle.h"
Particle::Particle(int X, int Y)
{
x = X + 5 + (rand()%25);
y = Y + 5 + (rand()%25);
frame = rand() % 5;
switch(rand()%3)
{
case 0:
type = red;
break;
case 1:
type = green;
break;
case 2:
type = blue;
break;
}
}
As you may have noticed I declared a few pointers red, green, blue which I use to define the member functions of the class I have created in the header file. Those same pointers are again used in the main source file. So now its obvious why i get the message:
1>Particle.obj : error LNK2005: "struct SDL_Surface * red" (?red@@3PAUSDL_Surface@@A) already defined in main.obj
when I try to compile and run my program.
Solution
The way you solve this problem is to explicitly declare variables you want to be globally used as external variables using the keyword
etern
. A quick reference about the extern keyword can be found
here. When you use the word
extern
it is a way of declaring the variable exists but will be defined a value elsewhere. So now when I include my header file in my source file and declare my pointers as such:
SDL_Surface *red;
The compiler understands that there exists a pointer called red and it may be defined elsewhere.
It is important also to define it elsewhere. That is why in my main.cpp source file I include the particles.h header file and I have the line:
SDL_Surface *red = NULL;
which explicitly defines my pointer. So now I can even call this pointer in another file and it will return the NULL value which I have just assigned.
So to recap:
Declare global variables and functions with the keyword extern in the header file
Define those global variables or functions in one< of the source files
Comments
One more thing I messed up regarding the same topic is to create a global variables header file. Every single declaration needs to be with the keyword extern. Also, For constant terms like:
const int screen_height=1000
declare them as constant static integers.
More over for declarations that don't need to be defined, such as unions, you only need to re-declare them in another source file. For example I say:
SDL_Event event;
in the header file. So in my main.cpp source file i say:
SDL_Event event;
Here is what my completed Global header file looks like:
#include
#include
#include
#ifndef GLOBALFNS
#define GLOBALFNS
//declare some poiters
extern SDL_Surface *dot;
extern SDL_Surface *screen;
extern SDL_Event event;
extern int ScreenW;
extern int ScreenH;
//external functions
extern "C++"{
//The dimensions of the dot
const static int DOT_WIDTH = 20;
const static int DOT_HEIGHT = 20;
//total paticles
const static int TOTAL_PARTICLES = 20;
//SDL supporting functions start
SDL_Surface* loadimg(std::string filename);
void applysurface(int x, int y, SDL_Surface* src, SDL_Surface* dst, SDL_Rect* clop);
}
#endif