1

I created a global file (Globals.h) to hold my global renderer (gRenderer) and my global window (gWindow). I declared them as extern as they'll be defined inside initWindow() & initRenderer() functions under InitChess.cpp.

Some reason the linker is complaining that I have "unresolved external symbols", even though I define them in functions under InitWindow.cpp.

Errors:

Severity Code Description Project File Line Suppression State Error LNK2001 unresolved external symbol "struct SDL_Window * gWindow" (?gWindow@@3PEAUSDL_Window@@EA)    Chess   C:\Users\\source\repos\Chess\Chess\InitChess.obj

Severity Code Description Project File Line Suppression State Error LNK2001 unresolved external symbol "struct SDL_Renderer * gRenderer" (?gRenderer@@3PEAUSDL_Renderer@@EA)    Chess   C:\Users\\source\repos\Chess\Chess\InitChess.obj

Chess.cpp:

#include "SDL.h"
#undef main
#include <iostream>
#include "../include/InitChess.h"

int main() 
{
    InitChess* e = new InitChess;
    e->initWindow();
    e->initRenderer();
    
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
        return 3;
    }

    delete e;
    return 0;
}

InitChess.h:

#pragma once
#include "SDL.h"
#include "../include/Globals.h"

class InitChess {
public:
    void initWindow();
    void initRenderer();

    ~InitChess();
private:

};

InitChess.cpp:

#include "../include/InitChess.h"

void InitChess::initWindow()
{
    SDL_Window* createdWindow;
    
    createdWindow = SDL_CreateWindow(
        "An SDL2 window",                  // window title
        SDL_WINDOWPOS_UNDEFINED,           // initial x position
        SDL_WINDOWPOS_UNDEFINED,           // initial y position
        640,                               // width, in pixels
        480,                               // height, in pixels
        SDL_WINDOW_OPENGL                  // flags
    );

    // assign created window to global window variable in Globals.h
    gWindow = createdWindow;
}

void InitChess::initRenderer()
{
    SDL_Renderer* createdRenderer;
    createdRenderer = SDL_CreateRenderer(gWindow, -1, 0);

    // assign created render to global renderer variable in Globals.h
    gRenderer = createdRenderer; 
}

InitChess::~InitChess()
{
    SDL_DestroyRenderer(gRenderer);
    SDL_Quit();
}

Globals.h:

#pragma once
#include "SDL.h"

#ifndef GLOBALS_H
#define GLOBALS_H

extern SDL_Window* gWindow;
extern SDL_Renderer* gRenderer;

#endif
genpfault
  • 51,148
  • 11
  • 85
  • 139
Svendy1126
  • 77
  • 1
  • 8
  • "I declared them as extern as they'll be defined in InitWindow.cpp.": Did you define them there and link the object file from that translation unit? You are not showing that file. – user17732522 Jan 12 '22 at 04:27
  • @user17732522 sorry about that, I have edited my question to reflect the issue. InitWindow.cpp holds the functions that declare the extern variables in Globals.h. Thanks. – Svendy1126 Jan 12 '22 at 04:37
  • You cannot define a global variable in a function. – n. m. could be an AI Jan 12 '22 at 04:40
  • "as they'll be defined inside initWindow() & initRenderer() functions under InitChess.cpp": You cannot define a global variable inside a function. You need to define it at global scope, otherwise you are just defining a local variable with the same name. Also, I don't see any definitions for `gWindow` and `gRenderer` in the functions. You are just assigning values. – user17732522 Jan 12 '22 at 04:40
  • 1
    Does this answer your question? [How to share a global variable between files using header file?](https://stackoverflow.com/questions/68253161/how-to-share-a-global-variable-between-files-using-header-file) – Stephen Newell Jan 12 '22 at 04:41
  • @user17732522 sorry, they are "initialized" in `initRenderer()` and `initWindow()` inside `InitChess.cpp` and declared in `Globals.h`. So architecturally, I need to create a .cpp file for my `Globals.h` to solve this scope issue, thus solving the linker issue.. right? – Svendy1126 Jan 12 '22 at 04:50

1 Answers1

1

There is a difference between a declaration and a definition.

Usually writing

SDL_Window* gWindow;

is a declaration and a definition of the variable gWindow.

Every (non-inline) variable that your program uses can have multiple declarations, but must have exactly one definition.

Putting extern before SDL_Window* gWindow; makes the declaration be not a definition.

Thus you still need to put a definition of gWindow somewhere. This must appear only once in the program and therefore you cannot put the definition in a header file which may be included in multiple .cpp files.

You need to choose one .cpp file and put the definition SDL_Window* gWindow; there. The definition must be at global scope, otherwise it is not referring to the same variable as the declaration extern SDL_Window* gWindow; in Globals.h.

In your code it seems that this file is supposed to be InitChess.cpp, but depending on your design it may be better to create a Globals.cpp and put the definitions there.


// assign created window to global window variable in Globals.h
gWindow = createdWindow;

This is not a definition and not even a declaration. It is just an assignment expression. A declaration for a variable starts with its type name. But as mentioned above, simply putting SDL_Window* in front of this line will not define the global variable declared in Globals.h. Instead it would declare and define a new local variable of the same name in the function.

user17732522
  • 53,019
  • 2
  • 56
  • 105