3

I am trying to initialize my game window and can't get past this error. I have tried:

  • double and triple checking all my code for syntax errors
  • checking that the SDL2 library is properly included in my project

Please see below code for your reference:

Header file:

#ifndef Game_hpp
#define Game_hpp
#include "SDL.h"
#include <iostream>

class Game
{
public:
    Game();
    ~Game();

    void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
    void handleEvents();
    void update();
    void render();
    void clean();

    bool running()
    {
        return isRunning;
    }

private:
    bool isRunning;
    SDL_Window *window;
    SDL_Renderer *renderer;
};

#endif /* Game_hpp */

Game.cpp - where functions are defined

 #include "Game.h"

Game::Game()
{}

Game::~Game()
{}

void Game::init(const char *title, int xpos, int ypos, int width, int height, bool fullscreen)
{
    int flags = 0;
    if (fullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }

    if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "Subsystems Initialised..." << std::endl;

        window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        if (window)
        {   
            std::cout << "Window Created" << std::endl;
        }

        renderer = SDL_CreateRenderer(window, -1, 0);
        if (renderer)
        {
            SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
            std::cout << "Renderer Created" << std::endl;
        }

        isRunning = true;
    }

    else
    {
        isRunning = false;
    }
}

void Game::handleEvents()
{
    SDL_Event event;
    SDL_PollEvent(&event);
    switch (event.type)
    {
        case SDL_QUIT:
            isRunning = false;
            break;

        default:
            break;
    }
}

void Game::update()
{}

void Game::render()
{
    SDL_RenderClear(renderer);
    //this is where we add stuff to render
    SDL_RenderPresent(renderer);
}

void Game::clean()
{
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    SDL_Quit();
    std::cout << "Game Cleaned." << std::endl;
}

Main function:

#include "Game.h"

Game *game = nullptr;

int main(int argc, const char * argv[])
{
    game = new Game();

    game->init("BirchEngine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, false);

    while (game->running())
    {
        game->handleEvents();
        game->update();
        game->render();
     }

    game->clean();

    return 0;
}

The errors I get:

1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol SDL_main referenced in function main_utf8

1>C:\Dev\2D_GameEngine\x64\Debug\2D_GameEngine.exe : fatal error LNK1120: 1 unresolved externals

Many thanks for your help!

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
Andrei
  • 373
  • 2
  • 3
  • 9
  • 1
    You have included the SDL headers (includes) correctly but not the SDL libraries (under **Linker** settings). – Mark Setchell Feb 10 '18 at 17:30
  • 1
    `Linker-->General-->Additional Library Directories` and `Linker-->Input-->Additional Dependencies` are probably what you are looking for to put `SDL_main.lib`. – Arnav Borborah Feb 10 '18 at 17:47
  • 1
    This is addressed by [FAQ](https://wiki.libsdl.org/FAQWindows#I_get_.22Undefined_reference_to_.27SDL_main.27.22_...). What Benjamin Lindley recommended would work too, but you'll lose what SDL2main does for you (compatibility with both GUI and console modes, automatic conversion of command line arguments to UTF8). – keltar Feb 11 '18 at 05:15
  • If Benjamin Lindley's answer solved your problem, you should *accept* it by pressing the green tick to the left of it and probably upvoting it. Adding any kind of "solved!" marks to the question or the title is generally frowned upon. – HolyBlackCat Feb 12 '18 at 12:01
  • Does the compiler know where SDL lib is? – Onur Tuna Feb 12 '18 at 13:45
  • Thx @HolyBlackCat, I wasn't aware. – Andrei Feb 13 '18 at 13:39
  • See https://stackoverflow.com/questions/18811243/unresolved-external-symbol-sdl-main-referenced-in-function-error-in-visual-st Basically, your `main` function needs to be this signature: `int main(int argc, char* argv[])`. You're using a `const char*` for argv. – altschuler Jun 08 '21 at 17:23

1 Answers1

14

SDL (unfortunately, IMO) does this strange thing where they redefine main, in order to abstract away platform specific details of the entry point in applications. In order to not utilize this feature, perform the following. Before including SDL.h, first define SDL_MAIN_HANDLED.

#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>

That inhibits the redefinition of main. Then, in main, before doing anything else with SDL, call this function

SDL_SetMainReady();

That will do any initialization that is needed by SDL (currently does nothing other than setting a global variable named SDL_MainIsReady to true).

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • Many thanks Bejamin Lindley, sorted now :) – Andrei Feb 11 '18 at 13:31
  • This doesn't look right to me. `SDL_SetMainReady()` does not do any initialization on any platform, it does a different thing. Quoting SDL docs: *"This is called by the real SDL main function to let the rest of the library know that initialization was done properly. Calling this yourself without knowing what you're doing can cause crashes and hard to diagnose problems with your application."* Check keltar's comment under the main post. – HolyBlackCat Feb 11 '18 at 13:46
  • @Andrei I would look for a better solution. Not only it has some disadvantages, mentioned in comments to your question, it also may not work with other versions of SDL or on other plaftorms. – HolyBlackCat Feb 11 '18 at 13:48
  • 1
    @HolyBlackCat: The initialization that SDL does before calling `SDL_SetMainReady` has nothing to do with SDL. It simply does stuff that is intended to make the main function on every platform look the same. If you're not going to ever do anything but program in SDL, then fine. Use their main. But I would recommend not doing that, and I think a third-party library redefining a symbol that is part of the language standard is a terrible practice. What if I'm using two different libraries that both decide to do that? Luckily, Sam Lantinga gave you an easy way to opt out of the feature. – Benjamin Lindley Feb 11 '18 at 14:44