Redefinition Errors with Include guard?

Feb 6, 2013 at 11:30pm
I have my files, main.cpp, CEXI.h, and CEXI.cpp
Here is the important code in the three files: (The rest of my code will be down below)

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <string>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

#include "CEXI.h"

bool Done = false;
SDL_Surface *Screen;
SDL_Surface *message;
SDL_Rect messageRect;
TTF_Font *font;
SDL_Color textColor = {255, 255, 255};


CEXI.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma once

#include <string>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

// CEXI_CORE
std::string CEXI_CORE_VERSION;

// CEXI_DATA
int CEXI_DATA_MAXIMAGES;
SDL_Surface *CEXI_DATA_IMAGES;
bool CEXI_DATA_IMAGESLOTS;

// CEXI_DRAW
int CEXI_DRAW_LoadImage(std::string);
SDL_Surface CEXI_DRAW_GetImage(int);


CEXI.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <string>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

#include "CEXI.h"

// CEXI_CORE
std::string CEXI_CORE_VERSION = "r0";

// CEXI_DATA
int CEXI_DATA_MAXIMAGES = 100;
SDL_Surface *CEXI_DATA_IMAGES = new SDL_Surface[CEXI_DATA_MAXIMAGES];
bool CEXI_DATA_IMAGESLOTS = new bool[CEXI_DATA_MAXIMAGES];


And here are my errors:
1
2
3
4
5
6
7
8
9
10
11
CEXI.cpp:10:13: error: redefinition of 'std::string CEXI_CORE_VERSION'
CEXI.h:10:13: error: 'std::string CEXI_CORE_VERSION' previously declared here
CEXI.cpp:13:5: error: redefinition of 'int CEXI_DATA_MAXIMAGES'
CEXI.h:13:5: error: 'int CEXI_DATA_MAXIMAGES' previously declared here
CEXI.cpp:14:14: error: redefinition of 'SDL_Surface* CEXI_DATA_IMAGES'
CEXI.h:14:14: error: 'SDL_Surface* CEXI_DATA_IMAGES' previously declared here
CEXI.cpp:15:6: error: redefinition of 'bool CEXI_DATA_IMAGESLOTS'
CEXI.h:15:6: error: 'bool CEXI_DATA_IMAGESLOTS' previously declared here
CEXI.cpp:20:34: error: invalid types 'bool[int]' for array subscript
CEXI.cpp:21:45: error: cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'SDL_Surface* IMG_Load(const char*)'
CEXI.cpp:22:35: error: invalid types 'bool[int]' for array subscript




Alrighty, so I look at this and see 'redefinition error' and think maybe its including my header twice. However, that wouldn't be possible with the #pragma once line at the top...

I also see 'invalid type bool[int]'. Whats that about? I have read that this is caused by redefining an array, so it may also be caused by the 'double-inclusion' problem I seem to be having.

Maybe an explanation of what I'm trying to do would help:
I want to try my hand at some simple GUI app with C++ and SDL. Regardless if people say I'm ready for it or not, I'm still gonna try it :P
main.cpp is my main loop and event handing, global declarations, etc.
CEXI is something I thought of that I think would help me in my other programs.
CEXI will be my 'interface' between me and SDL. I can make some functions in CEXI.cpp that will simplify tasks such as creating and blitting graphics, so that whenever I am going to use SDL in another one of my programs, I can include CEXI.h to easily implement my custom SDL functions.
I have tried several ways to organizing it, such as using structs withing structs to categorize variables and functions.
For example, I would call cexi.draw.loadImage() to load an image, or cexi.data.mainLoopBool = false; to change the value of the main loop variable (effectively ending the program).
I have also tried classes to get the same effect, but I just got more and more errors, until I decided I would format my interface like SDL or OpenGL, such that each 'module' of my interface is separated like so:
1
2
CEXI_DRAW_xxxx
CEXI_DATA_yyyy

But again, I still get errors. These however, I think understand, and thought I knew how to fix, until when I tried, and it didn't work...

So I come to the cplusplus community for help :D

At this point, my program will only build if I comment everything out in CEXI.cpp
I don't know why that works, but I would assume it would get rid of the 'redefinition errors' since that contains the only other uses of CEXI

I haven't actually used anything from my interface yet, but since this is a simple hello world program in SDL, I will later move some tasks from main.cpp into CEXI so that I can re-create the entire program using mainly my interfaces functions and variables.



Some extra info:

I'm running Windows 8 64-bit, however I made sure I am using the 32-bit code::blocks and 32-bit libraries. (so that my programs will also run on 32-bit systems)

I am using the latest stable version of Code::Blocks, and the MinGW suite that came with it.

The program DID work before (without CEXI), and I only started experiencing errors once I had created and tried to include CEXI.h, so there shouldn't be any problems in main.cpp

All files are located in the same directory

I HAVE looked up my problem several times on Google. I am not a noob. I have read the other posts, and they have not helped me with my specific scenario. If you can understand that I'm still learning, and may make pathetic mistakes, and answer my question, I would appreciate it very much. Nothing against the individual reader, however, I have tried to tackle this myself, and have failed, so that is why I am making a topic about it.

With that said, Thank you very much in advance! It's very hard to experiment with my programming skills with all these confusing errors!


Entire main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <string>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

#include "CEXI.h"

bool Done = false;
SDL_Surface *Screen;
SDL_Surface *message;
SDL_Rect messageRect;
TTF_Font *font;
SDL_Color textColor = {255, 255, 255};

bool Init();
void Event();
void Process();
void Draw();
void Exit();

int main (int argc, char **argv){
    if(!Init()){
        return 1;
    }

    while (!Done){
        Event();
        Process();
        Draw();
    }

    Exit();
    return 0;
}

bool Init(){
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0 ){
        return false;
    }
    Screen = SDL_SetVideoMode(1600, 900, 16, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN);
    if (!Screen){
        return false;
    }
    if(TTF_Init() != 0){
        return false;
    }
    font = TTF_OpenFont("8bitlim.ttf",100);
    if(!font){
        return false;
    }
    message = TTF_RenderText_Solid(font,"Hello World!",textColor);
    if(!message){
        return false;
    }
    return true;
}

void Event(){
    SDL_Event Event;
    while(SDL_PollEvent(&Event)){
        switch(Event.type){
            case SDL_QUIT:{
                Done = true;
                break;
            }
            case SDL_KEYDOWN:{
                if(Event.key.keysym.sym == SDLK_ESCAPE){
                    Done = true;
                    break;
                }
            }
        }
    }
}

void Process(){
    messageRect.x = (Screen->w / 2) - (message->w / 2);
    messageRect.y = (Screen->h / 2) - (message->h / 2);
}

void Draw(){
    SDL_FillRect(Screen, 0, SDL_MapRGB(Screen->format, 0, 0, 0));

    SDL_BlitSurface(message, NULL, Screen, &messageRect);

    SDL_Flip(Screen);
}

void Exit(){
    TTF_CloseFont(font);
    TTF_Quit();
    SDL_FreeSurface(message);
    SDL_FreeSurface(Screen);
    SDL_Quit();
}


Entire CEXI.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma once

#include <string>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

// CEXI_CORE
std::string CEXI_CORE_VERSION;

// CEXI_DATA
int CEXI_DATA_MAXIMAGES;
SDL_Surface *CEXI_DATA_IMAGES;
bool CEXI_DATA_IMAGESLOTS;

// CEXI_DRAW
int CEXI_DRAW_LoadImage(std::string);
SDL_Surface CEXI_DRAW_GetImage(int);


Entire CEXI.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <string>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

#include "CEXI.h"

// CEXI_CORE
std::string CEXI_CORE_VERSION = "r0";

// CEXI_DATA
int CEXI_DATA_MAXIMAGES = 100;
SDL_Surface *CEXI_DATA_IMAGES = new SDL_Surface[CEXI_DATA_MAXIMAGES];
bool CEXI_DATA_IMAGESLOTS = new bool[CEXI_DATA_MAXIMAGES];

// CEXI_DRAW
int CEXI_DRAW_LoadImage(std::string f){
    for(int i=1; i < CEXI_DATA_MAXIMAGES; i++){
        if(CEXI_DATA_IMAGESLOTS[i] == false){
            CEXI_DATA_IMAGES[i] = IMG_Load(f);
            CEXI_DATA_IMAGESLOTS[i] = true;
            return i;
        }
    }
    return -1;
}

SDL_Surface CEXI_DRAW_GetImage(int n){
    return CEXI_DATA_IMAGES[n];
}
Feb 7, 2013 at 12:22am
Putting global variables in header files doesn't work (not without trickery). Each individual cpp file thinks it's creating its own version of the variable, then the linker gets confused because it doesn't know which one to use.

I made a big post on this recently... let me see if I can find it....


Here is one... but it's not the one I was thinking of.. still looking..
http://www.cplusplus.com/forum/general/71964/#msg383802




EDIT: nah couldn't find the one I was thinking of.

Anyway, long story short: don't put globals in a header file (or really, don't have globals at all). Pass data as parameters to functions that need them.
Last edited on Feb 7, 2013 at 12:27am
Feb 7, 2013 at 9:22am
@Disch
So what I did was, after reading your post, I used the extern keyword with the declarations in my header. It solved most of my errors.

However, I am still stuck with these:
1
2
3
CEXI.cpp|20|error: invalid types 'bool[int]' for array subscript
CEXI.cpp|21|error: cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'SDL_Surface* IMG_Load(const char*)'
CEXI.cpp|22|error: invalid types 'bool[int]' for array subscript|


The error on line 20 and 22 can most likely be solved together, and the error on line 21 is from me trying to use a string for a char input. I may be able to figure that one out (although I never used chars before).

This is the last thing guys! Any ideas?

P.S. Thank you Disch for your answer, it solved a great deal of the errors.
Feb 7, 2013 at 9:31am
1
2
3
4
5
6
7
// bool CEXI_DATA_IMAGESLOTS = new bool[CEXI_DATA_MAXIMAGES];
bool* CEXI_DATA_IMAGESLOTS = new bool[CEXI_DATA_MAXIMAGES];

// ...

//CEXI_DATA_IMAGES[i] = IMG_Load(f);
CEXI_DATA_IMAGES[i] = IMG_Load( f.c_str() ) ;

Feb 7, 2013 at 9:43am
I have a question. Why are you using such libraries as SDL_image.h if you understand nothing in C++?!! You are even unable to read error messages!
So stop to use such libraries and read some book on C++ for very beginners.

This statement

bool CEXI_DATA_IMAGESLOTS = new bool[CEXI_DATA_MAXIMAGES];

is obvious invalid. Shall be

bool *CEXI_DATA_IMAGESLOTS = new bool[CEXI_DATA_MAXIMAGES];

I do not see the definition of IMG_Load but according to the error message its parameter is declared as const char * while you are trying to pass an object of type std::string that can not be implicitly converted to const char *

IMG_Load(f);

Feb 7, 2013 at 9:57am
@JLBorges
Thank you. Your bool *CEXI_DATA_IMAGESLOTS solved the two invalid type errors. Also, thank you for such a speedy response.

However.... @vlad
Did I not say I knew how to fix that error? (Or that I could fix it?)
Did I not post this in the Beginners forum?
Did I not say I was experimenting?
Did I not say I wouldn't care if someone told me I couldn't handle it?

Listen, I came here for help, not so I could be told I'm not good enough to do anything cool.

I appreciate your answer, but you don't have to be so rude when answering. I think I know C++ good enough to make little SDL tests for myself, and I don't need people like you telling me I know nothing of C++.

Anyways:
Thank you all who actually helped, It works now.
I will mark this topic as solved.
Feb 7, 2013 at 1:17pm
@CorruptionEX


It is not interesting what you were saying. I only wonder why beginners start to write for example OS in C++ while they are unable to write a simple C++ console program .:)

But there are more funny things that deserve to be mentioned. The compiler reports the error

CEXI.cpp|20|error: invalid types 'bool[int]' for array subscript

It looks strange enough if do not know that any scalar type implicitly can be converted to bool. In fact the reason of the error is the statement

bool CEXI_DATA_IMAGESLOTS = new bool[CEXI_DATA_MAXIMAGES];

But the problem is that statement is a correct statement if do not take into account the memory leak!:)

bool is the only type that allows to write such symantically incorrect statements and the compiler will not report any error.:)

Last edited on Feb 7, 2013 at 1:18pm
Topic archived. No new replies allowed.