54

After having some trouble setting up SDL, I found out that SDL defines a macro that replaces main:

#define main SDL_main

// And then
extern C_LINKAGE int SDL_main(int argc, char *argv[]);

This can also create compilation errors, if the main function doesn't have the argc and argv parameters defined.

This macro gives me headaches just when I see it... Why does SDL need to redefine main? After some more searching, I found that some people #undef main, and use it the normal way.

So this is the question: why does SDL need to redefine main, what does it do? Are there any side effects to undefining it?

One thing I noticed is that SDL redirects standard output and error to files (and I don't want this behavior), and this behavior stops if I undefine main.

Tibi
  • 4,015
  • 8
  • 40
  • 64
  • 1
    [You can disable this behavior.](https://wiki.libsdl.org/SDL_SetMainReady) – Kotauskas Jul 18 '19 at 14:50
  • 1
    Yeesh, lots of anger in this post. The main reason why this is done is to abstract over the different entry point on Windows (winmain) and the traditional entry point on other platforms (int main). It simplifies a lot of code that would otherwise need ifdefs or separate source files. It's a convenience mechanism and can be done manually if you so choose. – Qix - MONICA WAS MISTREATED Dec 25 '20 at 21:17

2 Answers2

59

Per the SDL Windows FAQ:

You should be using main() instead of WinMain() even though you are creating a Windows application, because SDL provides a version of WinMain() which performs some SDL initialization before calling your main code.

If for some reason you need to use WinMain(), take a look at the SDL source code in src/main/win32/SDL_main.c to see what kind of initialization you need to do in your WinMain() function so that SDL works properly.

SDL requires initialization, so it injects its own main function that runs its initialization before calling your "main" function, which it renames to SDL_main so that it does not conflict with the actual main function. As noted in the FAQ, your main function must be of the form

int main(int argc, char* argv[])
Community
  • 1
  • 1
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 41
    Almost every library requires initialization but this looks like a poor practice for how to do it. +1 anyway. – David Grayson Aug 15 '12 at 19:52
  • 28
    @DavidGrayson very poor practice indeed, especially if you have two libraries that do this...massive pain in the patooty – Captain Obvlious Aug 15 '12 at 19:54
  • 2
    Can I write my own implementation of main(), instead of using this strange SDL_main() function? There are some things (for example, stdout redirection) that are kind of pushed down my throat, and I don't want it. – Tibi Aug 15 '12 at 20:06
  • 2
    Agree with David. This macro is a C technique. C++ has many sane alternatives. – MSalters Aug 16 '12 at 08:56
  • 2
    Not only I agree with David about this being a poor practice, but SDL has it's own SDL_init call for initialization. As far as I recall, the initialization in SDLmain was pretty useless (redirection of console if I recall) – BlakBat Aug 22 '12 at 13:01
  • 1
    That is misleading in that I had to change my ``main()`` function into ``WinMain()`` anyway then changing the injection from ``main`` to ``WinMain`` in ``SDL_Main.h`` (which I include) to avoid having to ``#define SDL_MAIN_HANDLED`` (without handling it). Otherwise the compiler (MinGW + gcc 12) would complain ``WinMain()`` was missing. It seems the SDL team has made an update and didn't care to change the doc accordingly. That seems to make the injection work correctly anyway. – Dominic Grenier Dec 14 '22 at 17:12
13

While I agree that it's a strange practice, there are situations where this is a reasonable solution, though it largely depends on the platform. Consider that different platforms have different entry points. Windows is typically WinMain, Linux is main, interacting with Android happens in Java, WinRT uses C++/CX extensions, and so on. Program entry point and APIs can be very platform specific and SDL tries to save you the trouble of having to deal with this. If you're only targeting Windows and SDL is only there to save you the trouble of working with WIN32 API, you might not need it. But if you ever go beyond desktop, you'll find it useful in my opinion.

Mel
  • 139
  • 1
  • 3