3

Take a look at this below main.cpp taken from the book: OpenGL Superbible 7th.

#include "sb7.h"

class my_application : public sb7::application
{
    void render(double currentTime)
    {
        static const GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f };
        glClearBufferfv(GL_COLOR, 0, red);
    }
};

DECLARE_MAIN(my_application);

Inside sb7.h, the related piece of code about DECLARE_MAIN() is

#if defined _WIN32
#define DECLARE_MAIN(a)                             \
sb7::application *app = 0;                          \
int CALLBACK WinMain(HINSTANCE hInstance,           \
                     HINSTANCE hPrevInstance,       \
                     LPSTR lpCmdLine,               \
                     int nCmdShow)                  \
{                                                   \
    a *app = new a;                                 \
    app->run(app);                                  \
    delete app;                                     \
    return 0;                                       \
}
#elif defined _LINUX || defined __APPLE__
#define DECLARE_MAIN(a)                             \
int main(int argc, const char ** argv)              \
{                                                   \
    a *app = new a;                                 \
    app->run(app);                                  \
    delete app;                                     \
    return 0;                                       \
}
#else
#error Undefined platform!
#endif

What is the benefit of using this kind of unusual approach? Definitely the way the code is structured jeopardizes the readability but I'm guessing there is a point behind this. Note that, the authors are using a third party glfw to handle the window and user's inputs such as from keyboard and mouse. I don't see why they need to use 'CALLBACK WinMain()` which I know it is related solely to Windows OS. I would like to be honest here. It is good to see different ways.

CroCo
  • 5,531
  • 9
  • 56
  • 88
  • 1
    I'm not sure I understand the question. The entry point on `_WIN32` is `WinMain`, the entry point in most other environments is `main`. – Eljay May 01 '20 at 22:19
  • The purpose is to make the real code look consistent between platforms. The difference between Windows (WinMain) and Linux (main) is abstracted away in DECLARE_MAIN. Under Windows, `WinMain` is the default entry point of an application, as documented [here](https://learn.microsoft.com/en-us/windows/win32/learnwin32/winmain--the-application-entry-point). – dxiv May 01 '20 at 22:20
  • @Eljay but `main()` is a entry point in Windows OS. – CroCo May 01 '20 at 22:22
  • @CroCo -- Yes but `WinMain` is for GUI on windows. See my answer – xilpex May 01 '20 at 22:23
  • @CroCo On MS-Windows `main` is the entry point for console applications and `WinMain` for graphical applications. – Richard Critten May 01 '20 at 22:23
  • @Croco In Windows `[w]WinMain` is the default entry point (unless you override it with a linker setting). `main` is only made available courtesy of the CRT library, which provides a default `WinMain` that unpacks the arguments and calls `main`. – dxiv May 01 '20 at 22:27
  • @dxiv so you're saying if I use `main()` as a normal C++ project in Visual Studio, it will be converted internally so that the entry point will be `WinMain`?! – CroCo May 01 '20 at 22:30
  • @CroCo -- I've updated my post with the answer. – xilpex May 01 '20 at 22:31
  • @Croco That depends on the compiler and linker, on their settings, and on whether the app uses the CRT or not. For example, a default console app built with Visual C++ in Windows will have an entry point of `mainCRTStartup`. But that's "hidden" in the CRT code, you will only see the familiar `main`. – dxiv May 01 '20 at 22:34
  • The benefit in a book is simplifying the book, by ASSUMING all programs use the `DECLARE_MAIN()` macro. The macro (conditionally) uses different entry points, so presented code samples will work on windows, linux, and other operating systems that all use different entry points for GUI based programs. The book is shorter and easier to write since boilerplate code doesn't need to be repeated in every code sample. Printing also consumes less paper. If the reader writes different code for the program entry point, then they can't blame the book's authors and publisher if code samples don't work – Peter May 02 '20 at 00:22

2 Answers2

0

WinMain is for the Windows API (like GUI and all). main is for terminal/console application. It is written how it is so that the main declaration is normal across all the platforms. I did a little digging and found that WinMain is there to remove the console on windows. Look here.

xilpex
  • 3,097
  • 2
  • 14
  • 45
  • You are missing my point. The authors are using third party to handle GUI via GLFW. I don't see any point with `WinMain`. – CroCo May 01 '20 at 22:23
  • @CroCo -- That is odd... But if you look at the top, this line: `sb7::application *app = 0;` is only there for windows. – xilpex May 01 '20 at 22:27
-1

On windows WinMain is the non-standard entry point for a GUI application. So this is what the code is reflecting. The code only works on windows and linux/apple

#if defined _WIN32
//...
#elif defined _LINUX || defined __APPLE__
//...
#else
#error Undefined platform!
#endif
bolov
  • 72,283
  • 15
  • 145
  • 224