0

So I'm working on a game for my computer science class using Dev-C++ 5.11 and Allegro 4.2, I'm reaching the end of the project and I want to finally fix a problem I've been having for a while now. My code is rather long to use a single .cpp file, but when I try to place my functions in a separate file I receive a series of "multiple definition of '' first defined here" errors. I've looked online and most people who have this problem have included their .cpp file in their main or something equivalent, but I have not done this and can't figure out why it won't work. The errors points to all the variables I declare in the header (the bitmaps as well as the char array and ints).

Files:

asteroidsMain.cpp
functions.cpp
asteroids.h

I also use a data file.

Main file:

#include <allegro.h>
#include <alfont.h> 
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "asteroids.h"
#include "asteroids_data.h"

//Creating movement timer (also used for typing)
volatile long speed_counterA = 0;

void increment_speed_counterA() {
    speed_counterA++;
}
END_OF_FUNCTION(increment_speed_counterA); 

//Creating laser timer
volatile long speed_counterB = 0;

void increment_speed_counterB() {
    speed_counterB++;
}
END_OF_FUNCTION(increment_speed_counterB); 

//Creating asteroid timer
volatile long speed_counterC = 0;

void increment_speed_counterC() {
    speed_counterC++;
}
END_OF_FUNCTION(increment_speed_counterC); 


int main() {
    //Initializations
    allegro_init();
    alfont_init();
    set_color_depth(desktop_color_depth());
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
    install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL);
    install_keyboard();
    install_mouse();
    install_timer();

    //Movement timer
    LOCK_VARIABLE(speed_counterA);
    LOCK_FUNCTION(increment_speed_counterA);
    install_int_ex(increment_speed_counterA, BPS_TO_TIMER(60));
    //Laser firing timer
    LOCK_VARIABLE(speed_counterB);
    LOCK_FUNCTION(increment_speed_counterB);
    install_int_ex(increment_speed_counterB, BPS_TO_TIMER(60));
    //Asteroid generation timer
    LOCK_VARIABLE(speed_counterC);
    LOCK_FUNCTION(increment_speed_counterC);
    install_int_ex(increment_speed_counterC, BPS_TO_TIMER(60));

    //Randomizing seed
    srand(time(0));

    //Creating/loading BITMAPs formain game
    BITMAP *buffer = create_bitmap(800, 600);
    shipStopped = loadImage("shipStopped");
    shipMoving = loadImage("shipMoving");
    laserSprite = loadImage("laser");
    smallAsteroid = loadImage("small_Asteroid");
    medAsteroid = loadImage("med_Asteroid");
    largeAsteroid = loadImage("large_Asteroid");

    //General use variables for screen control
    int onScreen = 0, i = 0, j = 0;
    bool quit = false;

    //Retrieving and sorting scores
    numOfScores = getHighs(name, score);
    sortHighs(name, score);

    //Loads main screen
    onScreen = changeScreen(0);

    while (!quit) {
        //If there was an issue loading datafile, error is returned
        if (onScreen == -1) {
            return 1;
        }
        else if (onScreen == 0) {   
            while (onScreen == 0) {
                //Primary check is for quitting program, other buttons lead to separate screens
                if ((mouse_b & 1) && mouse_x > 400 - 75 && 
                mouse_x < 400 + 75 && mouse_y > 450 && mouse_y < 4505 + quitButton->h) { //For clicking Quit
                    quit = true;
                    onScreen = -2;
                }
                else if ((mouse_b & 1) && mouse_x > 400 - 75 && 
                mouse_x < 400 + 75 && mouse_y > 150 && mouse_y < 150 + playButton->h) { //For clicking Play
                    onScreen = changeScreen(2);
                }
                else if ((mouse_b & 1) && mouse_x > 400 - 75 && 
                mouse_x < 400 + 75 && mouse_y > 250 && mouse_y < 250 + highsButton->h) { //For clicking Highscores
                    onScreen = changeScreen(3);
                }
                else if((mouse_b & 1) && mouse_x > 400 - 75 && 
                mouse_x < 400 + 75 && mouse_y > 350 && mouse_y < 350 + creditsButton->h) { //For clicking Credits
                    onScreen = changeScreen(4);
                }
            }
        }
        else if (onScreen == 2) { //Difficulty choice screen
            if ((mouse_b & 1) && mouse_x > 600 - (playButton->w / 2) && 
                mouse_x < 600 + (playButton->w / 2) && mouse_y > 192 && mouse_y < 192 + playButton->h) {
                    onScreen = changeScreen(1);
        }
            else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
            mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
                onScreen = changeScreen(0);
            }
        }
        else if (onScreen == 3) { //Highscore screen
            if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
            mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
                onScreen = changeScreen(0);
            }
        }
        else if (onScreen == 4) { //Credit screen
            if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
            mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
                onScreen = changeScreen(0);
            }
        }
        else if (onScreen == 51) { //Game over screen

            if (points <= score[9]) {
                if ((mouse_b & 1) && mouse_x > 25 && mouse_x < 175 &&
                    mouse_y > 575 - menuButton->h && mouse_y < 575) { //Begins a new game
                    onScreen = changeScreen(2);
                }
                else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 &&
                         mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
                    onScreen = changeScreen(0);
                }
            }
            else {
                if (mouse_b & 1) {
                    //Adding new highschore to array
                    score[9] = points;
                    strcpy(name[9], "");

                    if (numOfScores < 10) {
                        numOfScores++;
                    }
                    onScreen = changeScreen(52);
                }
            }
        }
        else if (onScreen == 52) {
            speed_counterA = 0;

            int keyEnt = 0, len = 0;
            char keyHold;

            //Text entering for highscore name, moves to next screen on enter
            while (!key[KEY_ENTER]) {
                //Preventing multiple printing of same key
                while (keypressed() && speed_counterA % 3 == 0) {
                    //Reading key from keyboard and making it useable
                    keyEnt = readkey();
                    keyHold = keyEnt & 0xff;

                    if (keyHold >= 32 && keyHold <= 126) { //Adding chars to name string
                        len = strlen(name[9]);

                        if (len < 19) { //Restricting the number of characters you can enter, beyond this does not save properly
                        name[9][len] = keyHold;
                        name[9][len + 1] = '\0';
                    }
                    }
                    else if (key[KEY_BACKSPACE]) { //Deleting if backspace char is pressed
                        name[9][len] = '\0';
                        len--;
                    }
                    clear_keybuf();
                }
                //Printing text
                textprintf_centre_ex(buffer, font, 400, 300, WHITE, -1, "What is your name: %s", name[9]);
                textprintf_centre_ex(buffer, font, 400, 500, WHITE, -1, "** press enter to conitue **");
                // Blit the buffer
                blit(buffer, screen, 0, 0, 0, 0, 800, 600); 
                clear(buffer);

            }
            onScreen = changeScreen(53);
        }
        else if (onScreen == 53) {
            if ((mouse_b & 1) && mouse_x > 25 && mouse_x < 175 &&
                mouse_y > 575 - menuButton->h && mouse_y < 575) { //Begins a new game
                onScreen = changeScreen(2);
            }
            else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 &&
                     mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
                onScreen = changeScreen(0);
            }
        }
        else if (onScreen == 1) { //Game screen
            //Defining 
            Laser laser[50];
            Asteroid asteroid[10];

            //Initializing lasers and asteroids
            for (i = 0; i < 50; i++) {
                laser[i].pos.x = 0;
                laser[i].pos.y = 0;
                laser[i].angle = 0;
                laser[i].onScreen = false;
            }
            for (i = 0; i < 10; i++) {
                asteroid[i].pos.x = 0;
                asteroid[i].pos.y = 0;
                asteroid[i].angle = 0;
                asteroid[i].onScreen = false;
            }

            //Game specific variables, reset for every new game
            int move = 0, lasers= 0, asteroids = 0;
            float angle = 0;
            bool collide = false;

            points = 0;

            //Spawning ship when game screen loads
            Coordinate ship;
            ship.x = 400 - (shipStopped->w / 2);
            ship.y = 300 - (shipStopped->h / 2);

            //Reseting game timers
            speed_counterA = 0;
            speed_counterB = 0;
            speed_counterC = 0;

            while (onScreen == 1) { //Game screen
                while (speed_counterA > 0) {

                    //Ship movement
                    if (key[KEY_UP] && key[KEY_RIGHT]){
                        ship.y -= 3;
                        ship.x += 3;
                        angle = 32;
                    }
                    else if (key[KEY_UP] && key[KEY_LEFT]){
                        ship.y -= 3;
                        ship.x -= 3;
                        angle = 224;
                    }
                    else if (key[KEY_DOWN] && key[KEY_RIGHT]) {
                        ship.y += 3;
                        ship.x += 3;
                        angle = 96;
                    }
                    else if (key[KEY_DOWN] && key[KEY_LEFT]) {
                        ship.y += 3;
                        ship.x -= 3;
                        angle = 160;
                    }
                    else if (key[KEY_UP]){
                        ship.y -= 6;
                        angle = 0;
                    }
                    else if (key[KEY_RIGHT]) {
                        ship.x += 6;
                        angle = 64;
                    }
                    else if (key[KEY_LEFT]) {
                        ship.x -= 6;
                        angle = 192;
                    }
                    else if (key[KEY_DOWN]) {
                        ship.y += 6;
                        angle = 128;
                    }

                    //Laser movement
                    for (i = 0; i < 50; i++) {
                        laser[i] = moveLaser(laser[i]);
                    }

                    //Asteroid movement
                    for (i = 0; i < 10; i++) {
                        asteroid[i] = moveAsteroid(asteroid[i]);
                    }

                    speed_counterA--;
                }

                //Key trigger for laser firing, if is first as having timer first 
                //would cause many hits not to be properly registered especially if 
                //tapping too fast, this allows firing at will with a fastest firing of every 0.15s
                if (key[KEY_SPACE]) {
                    //Laser firing timer
                    while (speed_counterB > 9) {
                        //Laser shooting
                        laser[lasers] = fireLaser(angle, ship.x, ship.y);

                        if (lasers >= 49) {
                            lasers = 0;
                        }

                        lasers++;

                    speed_counterB -= 10;
                    }
                }   

                //Asteroid spawning counter
                while (speed_counterC > 59) { //Spawns an asteroiud every second

                    //Keeping asteroids within array range
                    if (asteroids >= 9){
                        asteroids = 0;
                    }

                    //Generating asteroid
                    asteroid[asteroids] = genAsteroid(1, -1);

                    asteroids++;
                    speed_counterC -= 60;
                }

                //If ship goes out top, it comes in bottom; vice versa
                if (ship.y <= 0 - ((shipStopped->h / 2))) {
                    ship.y += (600);
                }
                else if (ship.y >= 600 - ((shipStopped->h / 2))) {
                    ship.y -= (600);
                }

                //If ship goes out left, it comes in right; vice versa
                if (ship.x <= 0 - ((shipStopped->w / 2))) {
                    ship.x += (800);
                }
                else if (ship.x >= 800 - ((shipStopped->w / 2))) {
                    ship.x -= (800);
                }

                //Drawing lasers
                for (i = 0; i < 50; i++) {
                    if (laser[i].onScreen) {
                        rotate_sprite(buffer, laserSprite, laser[i].pos.x, laser[i].pos.y, ftofix(laser[i].angle)); 
                    }
                }

                //Drawing ship
                if (key[KEY_UP] || key[KEY_DOWN] || key[KEY_LEFT] || key[KEY_RIGHT]) {
                    rotate_sprite(buffer, shipMoving, ship.x, ship.y, ftofix(angle)); //Ship sprite with engines firing
                }
                else {
                    rotate_sprite(buffer, shipStopped, ship.x, ship.y, ftofix(angle)); //Ship sprite no flames

                }

                //Drawing asteroids
                for (i = 0; i < 10; i++) {
                    if (asteroid[i].onScreen == true) {
                        //Drawing sprite based on asteroid type
                        if (asteroid[i].type == 1) { //Large asteroid
                            draw_sprite(buffer, largeAsteroid, asteroid[i].pos.x, asteroid[i].pos.y);
                        }
                        else if (asteroid[i].type == 2) { //Medium asteroid
                            draw_sprite(buffer, medAsteroid, asteroid[i].pos.x, asteroid[i].pos.y);
                        }
                        else if (asteroid[i].type == 3) { //Small asteroid
                            draw_sprite(buffer, smallAsteroid, asteroid[i].pos.x, asteroid[i].pos.y);
                        }
                    }
                }

                //Checks bb collisions
                for (i = 0; i < 50; i++) {
                    for (j = 0; j < 10; j++) {
                        if (laser[i].onScreen && asteroid[j].onScreen) {
                            collide = checkCollision(asteroid[j].type, 0, asteroid[j].pos, laser[i].pos);
                            if (collide) {
                                laser[i].onScreen = false;
                                asteroid[j].onScreen = false;

                                points += 100 * asteroid[j].type;

                                //Splitting med or large asteroids into 2 asteroids one type down
                                if (asteroid[j].type < 3) { 
                                    asteroid[asteroids] = splitAsteroid(1, asteroid[j]);
                                    asteroid[j] = splitAsteroid(2, asteroid[j]);
                                    asteroids++;
                                }
                            }
                        }
                    }
                }

                //Printing score
                textprintf_ex(buffer, font, 10, 5, WHITE, -1, "Score: %d", points);
                textprintf_ex(buffer, font, 660, 5, WHITE, -1, "Press esc to quit");

                // Blit the buffer
                blit(buffer, screen, 0, 0, 0, 0, 800, 600); 
                clear(buffer);

                for (i = 0; i < 10; i++) {
                    if (asteroid[i].onScreen) {
                        collide = checkCollision(asteroid[i].type, 1, asteroid[i].pos, ship);

                        if (collide) {
                            onScreen = changeScreen(51);
                        }   
                    }
                }

                //To leave game screen and return to main menu
                if (key[KEY_ESC]) {
                    onScreen = changeScreen(0);
                }
            }
        }
    }

    //Freeing memory
    destroy_bitmap(playButton);
    destroy_bitmap(highsButton);
    destroy_bitmap(creditsButton);
    destroy_bitmap(quitButton);
    destroy_bitmap(shipStopped);
    destroy_bitmap(shipMoving);
    destroy_bitmap(laserSprite);
    destroy_bitmap(smallAsteroid);
    destroy_bitmap(medAsteroid);
    destroy_bitmap(largeAsteroid);

    return 0;
}
END_OF_MAIN()

Header file is:

#ifndef ASTEROIDS_H_
#define ASTEROIDS_H_

#define WHITE makecol(255, 255, 255)
#define BLACK makecol(0, 0, 0)

#include <allegro.h>
#include <alfont.h> 

//Made global so size pointers can be used throughout
BITMAP *playButton;
BITMAP *playAgainButton;
BITMAP *highsButton;
BITMAP *creditsButton;
BITMAP *quitButton;
BITMAP *menuButton;
BITMAP *shipStopped;
BITMAP *shipMoving;
BITMAP *laserSprite;
BITMAP *smallAsteroid;
BITMAP *medAsteroid;
BITMAP *largeAsteroid;

//Highscore variables are made global; technically bad, 
//but makes simplifies printing greatly
int score[10], numOfScores, points;
char name[10][20];

struct Coordinate {
    int x, y;
};

struct Laser {
    Coordinate pos;
    float angle;
    bool onScreen;
};

struct Asteroid {
    Coordinate pos;
    int type;
    int angle;
    bool onScreen;
};

int changeScreen(int toLoad);
BITMAP* loadImage(const char image[20]);
int getHighs(char name[][20], int high[]);
void sortHighs(char name[][20], int score[]);
void saveHighs(const char name[][20], const int score[], int numOfScores);
Laser fireLaser(float angle, int ship_x, int ship_y);
Laser moveLaser(Laser laser);
Asteroid genAsteroid(int difficulty, int type);
Asteroid splitAsteroid(int order, Asteroid asteroid);
Asteroid moveAsteroid(Asteroid asteroid);
bool checkCollision(int typeA, int typeB, Coordinate asteroid, Coordinate object);

#endif

The functions file boils down to:

#include <allegro.h>
#include <alfont.h> 
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "asteroids.h"
#include "asteroids_data.h"

/*~500 lines of functions*/

Everything works when I simply put the functions below the main

Copy of compile log:

g++.exe -c asteroidsMain.cpp -o asteroidsMain.o -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++" -I"C:/Program Files (x86)/Dev-Cpp/include" -m32
g++.exe asteroidsMain.o functions.o -o POPE_Greg_Asteroids.exe -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32" -L"C:/Program Files (x86)/Dev-Cpp/lib" -lalfont -lalleg -m32
functions.o:functions.cpp:(.bss+0x0): multiple definition of `playButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x0): first defined here
functions.o:functions.cpp:(.bss+0x4): multiple definition of `playAgainButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x4): first defined here
functions.o:functions.cpp:(.bss+0x8): multiple definition of `highsButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x8): first defined here
functions.o:functions.cpp:(.bss+0xc): multiple definition of `creditsButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0xc): first defined here
functions.o:functions.cpp:(.bss+0x10): multiple definition of `quitButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x10): first defined here
functions.o:functions.cpp:(.bss+0x14): multiple definition of `menuButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x14): first defined here
functions.o:functions.cpp:(.bss+0x18): multiple definition of `shipStopped'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x18): first defined here
functions.o:functions.cpp:(.bss+0x1c): multiple definition of `shipMoving'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x1c): first defined here
functions.o:functions.cpp:(.bss+0x20): multiple definition of `laserSprite'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x20): first defined here
functions.o:functions.cpp:(.bss+0x24): multiple definition of `smallAsteroid'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x24): first defined here
functions.o:functions.cpp:(.bss+0x28): multiple definition of `medAsteroid'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x28): first defined here
functions.o:functions.cpp:(.bss+0x2c): multiple definition of `largeAsteroid'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x2c): first defined here
functions.o:functions.cpp:(.bss+0x40): multiple definition of `score'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x40): first defined here
functions.o:functions.cpp:(.bss+0x68): multiple definition of `numOfScores'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x68): first defined here
functions.o:functions.cpp:(.bss+0x6c): multiple definition of `points'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x6c): first defined here
functions.o:functions.cpp:(.bss+0x80): multiple definition of `name'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x80): first defined here
collect2.exe: error: ld returned 1 exit status

C:\Users\Greg\Documents\Asteroids B\Makefile.win:25: recipe for target 'POPE_Greg_Asteroids.exe' failed
mingw32-make.exe: *** [POPE_Greg_Asteroids.exe] Error 1
Gapope
  • 11
  • 3
  • 2
    This isn't the problem, but names that contain two consecutive underscores (`__ASTEROIDS_H_INCLUDED__`) and names that begin with an underscore followed by a capital letter are reserved for use by the implementation. Don't use them in your code. – Pete Becker Jan 05 '17 at 21:32
  • Show the build log. We need to see at least some of the exact error messages. The messages will clearly point to where and what the multiple definitions are. That is obviously vital info for this question. – kaylum Jan 05 '17 at 21:35
  • 'I receive a series of "multiple definition of '' first defined here" errors' -- did you **read** the error messages? I've never seen a compiler that give this kind of error message without mentioning the **names** of the symbols that are multiply defined, and that's a big clue to how to fix the problem. Look for those names, and **remove** code that doesn't relate to them, until you have the smallest program you can come up with that shows the problem. You might just see how to fix it yourself. – Pete Becker Jan 05 '17 at 21:35
  • 1
    The lines in the header like `int score[10], numOfScores, points;` may cause that sort of error. If you `#include "asteroids.h"` in several different cpp files, you will define these variables once in each cpp. If the error is detected at linking, then that is probably the problem. Please provide a sample of the error messages. – adentinger Jan 05 '17 at 21:37
  • Have you tried to create the [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) that shows the problem? You only need to make a simple example and in doing so might see why it fails. – Weather Vane Jan 05 '17 at 21:39
  • The problem are all those global variables in the header which is included in both the "functions file" and the "main file", leading to double definitions. – Unimportant Jan 05 '17 at 21:42
  • I have removed the C tag. C and C++ are different languages and the answer to this question is likely to be different for each - C allows multiple definitions of global variables under certain conditions whereas C++ does not. – kaylum Jan 05 '17 at 21:45
  • @Unimportant My opinion exactly. @Gapope If this is the problem, an easy (though not ideal way IMO) to solve this is, in the header file, declare the variables as extern (`extern int score[10];` etc.) and, in `asteroids.cpp`, do a regular declaration (`int score[10];` etc.). That way, several files can use the same variables, that are only actually declared in `asteroids.cpp`. – adentinger Jan 05 '17 at 21:46
  • @kaylum : Can you elaborate ? How does C allow multiple definitions ? – Unimportant Jan 05 '17 at 21:51
  • 2
    @Unimportant Google "C tentative definitions". For example: [About Tentative definition](http://stackoverflow.com/questions/3095861/about-tentative-definition) – kaylum Jan 05 '17 at 21:56
  • As @PeteBecker said, you really should read the error message more carefully. None of them indicate multiple definitions of the same function as you have implied. They all point to multiple definition of variables which others have already explained as the problem. – kaylum Jan 05 '17 at 22:03
  • @PeteBecker I had been looking at them and I tried a few approaches to solve based off what I saw, but I am still relatively new to all of this and couldn't figure it out for myself. – Gapope Jan 05 '17 at 22:15
  • @kaylum I tried to tag you with the above message to petebecker, but was limited to only one – Gapope Jan 05 '17 at 22:15
  • @Unimportant I tried the extern approach, it didn't change anything – Gapope Jan 05 '17 at 22:16
  • 1
    You need to show us exactly what you tried. You may not have done it correctly but we can't tell you what unless you show us right? – kaylum Jan 05 '17 at 22:29
  • @Gapope The extern approch *should* work. Give a look at [this answer](http://stackoverflow.com/a/11056156/2252948) (look at the part which starting at *"If you need a global variable visible"*) to see how to use the `extern` keyword, and what it does. If you still can't make it work, I can post an actual answer giving an example ; just ask. – adentinger Jan 05 '17 at 22:53
  • So I don't know what the hell I was thinking earlier, but I was in a rush to try fixing things before I left my house, I'm back now and tried the `extern` approach again and it seems to have worked. I'd seen that suggestion before, but for some reason had never implemented it properly. Thank you @Unimportant – Gapope Jan 06 '17 at 01:39

2 Answers2

1

Variables declared in a header need to be marked as extern and be mirrored in a separate source file. If each source file includes your header as is, there will be multiple definitions of the same objects in different files and the redefinition errors will occur upon linking.

BugSquasher
  • 335
  • 1
  • 13
-1

Add those files in same project.