Right, I have looked at this post: Difference between WinMain,main and DllMain in C++
I now know that WINMAIN
is used for window applications and main()
for consoles. But reading the post doesn't really tell me why exactly what is the difference.
I mean what's the point of having separating different mains functions to start of a program? Is it due to performance issues? Or what is it?
According to @RaymondChen
The name WinMain is just a convention
DllMain and WinMain is different in their prototypes itself. WinMain accepts commandline argument while the other one talks about how it's attached to the process.
As per MSDN documentation
By default, the starting address is a function name from the C run-time library. The linker selects it according to the attributes of the program, as shown in the following table.
mainCRTStartup
(orwmainCRTStartup
) An application using/SUBSYSTEM:CONSOLE;
calls main (orwmain
)WinMainCRTStartup
(orwWinMainCRTStartup
) An application using/SUBSYSTEM:WINDOWS;
callsWinMain
(orwWinMain
), which must be defined with__stdcall
_DllMainCRTStartup
A DLL; callsDllMain
, which must be defined with__stdcall
, if it existsAbout the functions.
The C and C++ standards require any program (for a “hosted” C or C++ implementation) to have a function called
main
, which serves as the program's startup function. Themain
function is called after zero-initialization of non-local static variables, and possibly but not necessarily (!, C++11 §3.6.2/4) this call happens after dynamic initialization of such variables. It can have one of the following signatures:plus possible implementation-defined signatures (C++11 §3.6.1/2) except that the result type must be
int
.As the only such function in C++
main
has a default result value, namely 0. Ifmain
returns then after the ordinary function returnexit
is called with themain
result value as argument. The standard defines three values that guaranteed can be used: 0 (indicates success),EXIT_SUCCESS
(also indicates success, and is typically defined as 0), andEXIT_FAILURE
(indicates failure), where the two named constants are defined by the<stdlib.h>
header which also declares theexit
function.The
main
arguments are intended to represent the command line arguments for the command used to start the process.argc
(argument count) is the number of items in theargv
(argument values) array. In addition to those itemsargv[argc]
is guaranteed to be 0. Ifargc
> 0 – which is not guaranteed! – thenargv[0]
is guaranteed to either be a pointer to an empty string, or a pointer to the “name used to invoke the program”. This name may include a path, and it may be the name of the executable.Using the
main
arguments to obtain the command line arguments works fine in *nix, because C and C++ originated with *nix. However, the de facto Windows standard for the encoding of themain
arguments is Windows ANSI, which does not support general Windows filenames (such as, for a Norwegian Windows installation, filenames with Greek or Cyrillic characters). Therefore Microsoft chose to extend the C and C++ languages with a Windows-specific startup function calledwmain
, which has wide character based arguments encoded as UTF-16, which can represent any filename.The
wmain
function can have one of these signatures, corresponding to the standard signatures formain
:plus a few more that are not especially useful.
I.e.,
wmain
is a direct wide character based replacement formain
.The
WinMain
char
based function was introduced with Windows, in the early 1980's:where
CALLBACK
,HINSTANCE
andLPSTR
are defined by the<windows.h>
header (LPSTR
is justchar*
).Arguments:
the
hInstance
argument value is the base address of the memory image of the executable, it's primarily used to load resources from the executable, and it can alternatively be obtained from theGetModuleHandle
API function,the
hPrevInstance
argument is always 0,the
lpCmdLine
argument can alternatively be obtained from theGetCommandLine
API function, plus a bit of weird logic to skip the program name part of the command line, andthe
nCmdShow
argument value can alternatively be obtained from theGetStartupInfo
API function, but with modern Windows the first creation of a top level window does that automatically so it's not of any practical use.Thus, the
WinMain
function has the same drawbacks as standardmain
, plus some (in particular the verbosity and being non-standard), and no advantages of its own, so it's really inexplicable except possibly as a vendor lock-in thing. However, with the Microsoft tool chain it makes the linker default to the GUI subsystem, which some see as an advantage. But with e.g. the GNU toolchain it does not have such an effect so this effect cannot be relied on.The
wWinMain
wchar_t
based function is a wide character variant ofWinMain
, in the same way aswmain
is a wide character variant of standardmain
:where
WINAPI
is the same asCALLBACK
, andPWSTR
is simplywchar_t*
.There is no good reason to use any of the non-standard functions except the least known and least supported of them, namely
wmain
, and then just for convenience: that this avoids using theGetCommandLine
andCommandLineToArgvW
API functions to pick up UTF-16 encoded arguments.To avoid the Microsoft linker acting up (the GNU toolchain's linker doesn't), just set the
LINK
environment variable to/entry:mainCRTStartup
, or specify that option directly. This is the Microsoft runtime library entry point function that, after some initialization, calls the standardmain
function. The other startup functions have corresponding entry point functions named in the same systematic way.Examples of using the standard
main
function.Common source code:
foo.cpp
In the examples below (first with the GNU toolchain and then with the Microsoft toolchain) this program is first built as a console subsystem program, and then as a GUI subsystem program. A console subsystem program, or in short just a console program, is one that requires a console window. This is the default subsystem for all Windows linkers I've used (admittedly not a great many), possibly for all Windows linkers period.
For a console program Windows creates a console window automatically if needed. Any Windows process, regardless of subsystem, can have an associated console window, and at most one. Also, the Windows command interpreter waits for a console program program to finish, so that the program's text presentation has finished.
Conversely, a GUI subsystem program is one that doesn't require a console window. The command interpreter does not wait for a GUI subsystem program, except in batch files. One way to avoid the completion wait, for both kinds of program, is to use the
start
command. One way to present console window text from a GUI subsystem program is to redirect its standard output stream. Another way is to explicitly create a console window from the program's code.The program's subsystem is encoded in the executable's header. It's not shown by Windows Explorer (except that in Windows 9x one could “quick view” an executable, which presented just about the same information as Microsoft's
dumpbin
tool now does). There is no corresponding C++ concept.main
with the GNU toolchain.main
with Microsoft's toolchain:Examples of using Microsoft’s
wmain
function.The following main code is common to both the GNU toolchain and Microsoft toolchain demonstrations:
bar.cpp
wmain
with the GNU toolchain.The GNU toolchain doesn't support Microsoft's
wmain
function:The link error message here, about
WinMain
, is because the GNU toolchain does support that function (presumably because so much ancient code uses it), and searches for it as a last resort after failing to find a standardmain
.However, it's trivial to add a module with a standard
main
that calls thewmain
:wmain_support.cpp
Now,
wmain
with Microsoft’s toolchain.With Microsoft's toolchain the linker automatically infers the
wmainCRTStartup
entry point if no entry point is specified and awmain
function is present (it's unclear what happens if a standardmain
is also present, I haven't checked that in recent years):With a non-standard startup function such as
wmain
it is, however, probably best to specify the entry point explicitly, so as to be very clear about the intention:A standard C program is passed 2 parameters by the command line at start up:
char** argv
is an array of strings (char*
)int argc
is the number ofchar*
in argvThe booting function
WinMain
that programmers have to write for a windows program is slightly different.WinMain
takes 4 parameters that are passed to the program by Win O/S at start up:See my article How to create a basic window in C for more
I had an exe using _tWinMain and Configuration Properties.Linker.System.Subsystem: Windows (/SUBSYSTEM:WINDOWS). Later I wanted it to support cmdline args and print to the console so I added:
but that only worked by printing in another console window that went away so was not that useful. Below is the way I changed it to work with Console (/SUBSYSTEM:CONSOLE) in such a way as I could go back and forth, if I needed to.
I vaguely recall reading somewhere that Windows programs have a
main()
function. It is just hidden in a header or library somewhere. I believe thismain()
function initializes all of the variables needed byWinMain()
and then calls it.Of course, I'm a WinAPI noob, so I hope others who are more knowledgeable will correct me if I am wrong.