WINMAIN and main() in C++ (Extended)
About 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. The main
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:
int main()
int main( int argc, char* argv[] )
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. If main
returns then after the ordinary function return exit
is called with the main
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), and EXIT_FAILURE
(indicates failure), where the two named constants are defined by the <stdlib.h>
header which also declares the exit
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 the argv
(argument values) array. In addition to those items argv[argc]
is guaranteed to be 0. If argc
> 0 – which is not guaranteed! – then argv[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 the main
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 called wmain
, 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 for main
:
int wmain()
int wmain( int argc, wchar_t* argv[] )
plus a few more that are not especially useful.
I.e., wmain
is a direct wide character based replacement for main
.
The WinMain
char
based function was introduced with Windows, in the early 1980's:
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);
where CALLBACK
, HINSTANCE
and LPSTR
are defined by the <windows.h>
header (LPSTR
is just char*
).
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 standard main
, 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 of WinMain
, in the same way as wmain
is a wide character variant of standard main
:
int WINAPI wWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PWSTR lpCmdLine,
int nCmdShow
);
where WINAPI
is the same as CALLBACK
, and PWSTR
is simply wchar_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 the GetCommandLine
and CommandLineToArgvW
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 standard main
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
#undef UNICODE
#define UNICODE
#include <windows.h>
int main()
{
MessageBox( 0, L"Press OK", L"Hi", MB_SETFOREGROUND );
}
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.
[D:\dev\test]
> g++ foo.cpp
[D:\dev\test]
> objdump -x a.exe | find /i "subsys"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000003 (Windows CUI)
[544](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[612](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000003 __subsystem__
[636](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> g++ foo.cpp -mwindows
[D:\dev\test]
> objdump -x a.exe | find /i "subsys"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000002 (Windows GUI)
[544](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[612](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000002 __subsystem__
[636](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> _
main
with Microsoft's toolchain:
[D:\dev\test]
> set LINK=/entry:mainCRTStartup
[D:\dev\test]
> cl foo.cpp user32.lib
foo.cpp
[D:\dev\test]
> dumpbin /headers foo.exe | find /i "subsys"
6.00 subsystem version
3 subsystem (Windows CUI)
[D:\dev\test]
> cl foo.cpp /link user32.lib /subsystem:windows
foo.cpp
[D:\dev\test]
> dumpbin /headers foo.exe | find /i "subsys"
6.00 subsystem version
2 subsystem (Windows GUI)
[D:\dev\test]
> _
Examples of using Microsoft’s wmain
function.
The following main code is common to both the GNU toolchain and Microsoft toolchain demonstrations:
bar.cpp
#undef UNICODE
#define UNICODE
#include <windows.h>
#include <string> // std::wstring
#include <sstream> // std::wostringstream
using namespace std;
int wmain( int argc, wchar_t* argv[] )
{
wostringstream text;
text << argc - 1 << L" command line arguments:\n";
for( int i = 1; i < argc; ++i )
{
text << "\n[" << argv[i] << "]";
}
MessageBox( 0, text.str().c_str(), argv[0], MB_SETFOREGROUND );
}
wmain
with the GNU toolchain.
The GNU toolchain doesn't support Microsoft's wmain
function:
[D:\dev\test]
> g++ bar.cpp
d:/bin/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.1/../../../libmingw32.a(main.o):main.c:(.text.startup+0xa3): undefined reference to `WinMain
@16'
collect2.exe: error: ld returned 1 exit status
[D:\dev\test]
> _
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 standard main
.
However, it's trivial to add a module with a standard main
that calls the wmain
:
wmain_support.cpp
extern int wmain( int, wchar_t** );
#undef UNICODE
#define UNICODE
#include <windows.h> // GetCommandLine, CommandLineToArgvW, LocalFree
#include <stdlib.h> // EXIT_FAILURE
int main()
{
struct Args
{
int n;
wchar_t** p;
~Args() { if( p != 0 ) { ::LocalFree( p ); } }
Args(): p( ::CommandLineToArgvW( ::GetCommandLine(), &n ) ) {}
};
Args args;
if( args.p == 0 )
{
return EXIT_FAILURE;
}
return wmain( args.n, args.p );
}
Now,
[D:\dev\test]
> g++ bar.cpp wmain_support.cpp
[D:\dev\test]
> objdump -x a.exe | find /i "subsystem"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000003 (Windows CUI)
[13134](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[13576](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000003 __subsystem__
[13689](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> g++ bar.cpp wmain_support.cpp -mwindows
[D:\dev\test]
> objdump -x a.exe | find /i "subsystem"
MajorSubsystemVersion 4
MinorSubsystemVersion 0
Subsystem 00000002 (Windows GUI)
[13134](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 __major_subsystem_version__
[13576](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000002 __subsystem__
[13689](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __minor_subsystem_version__
[D:\dev\test]
> _
wmain
with Microsoft’s toolchain.
With Microsoft's toolchain the linker automatically infers the wmainCRTStartup
entry point if no entry point is specified and a wmain
function is present (it's unclear what happens if a standard main
is also present, I haven't checked that in recent years):
[D:\dev\test]
> set link=/entry:mainCRTStartup
[D:\dev\test]
> cl bar.cpp user32.lib
bar.cpp
LIBCMT.lib(crt0.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
bar.exe : fatal error LNK1120: 1 unresolved externals
[D:\dev\test]
> set link=
[D:\dev\test]
> cl bar.cpp user32.lib
bar.cpp
[D:\dev\test]
> _
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:
[D:\dev\test]
> cl bar.cpp /link user32.lib /entry:wmainCRTStartup
bar.cpp
[D:\dev\test]
> dumpbin /headers bar.exe | find /i "subsystem"
6.00 subsystem version
3 subsystem (Windows CUI)
[D:\dev\test]
> cl bar.cpp /link user32.lib /entry:wmainCRTStartup /subsystem:windows
bar.cpp
[D:\dev\test]
> dumpbin /headers bar.exe | find /i "subsystem"
6.00 subsystem version
2 subsystem (Windows GUI)
[D:\dev\test]
> _
WinMain vs. main (C++)
Talking about the Microsoft toolchain, conventionally, Win32 graphical applications have always started with WinMain
, while main
is used for console applications.
The difference between the two kinds of applications actually boils down (mostly) to a single setting in the executable, and is not in capability - a GUI application can create a console, and a console application can create a window - but in the behavior of the loader: for an exe marked as GUI the loader won't allocate any console, while a console exe will attach to the parent's console or create a new one if there isn't one.
For the entrypoint name, it is all just a matter of linker/CRT defaults: the "real" entry point of the executable is just an offset into the final executable, that points to a function that takes no parameters. It's the CRT that does its stuff, determines the parameters and then calls "your" entrypoint, so, in line of principle, they both could work exactly the same way.
The point is, the name/signature of the default entrypoint that the CRT looks for depends from the type of application you are building; if the compiler and linker are set to build a console application, they will look for a main
(or wmain
or _tmain
, depending on Unicode settings), for a GUI application they use WinMain
, and DllMain
for a dll.
So:
- use
WinMain
if you are building a GUI (=no console created for it at startup) application; main
for a console application;DllMain
for a dll.
Again, this all isn't written in stone (and there are ways to start a GUI application from a standard main
), but "when in Rome, do as the Romans do" - i.e. it's usually best to follow the uses of the platform to avoid confusing other developers and going through untested/unsupported compiler settings just to change the signature of the entrypoint.
Replacing WinMain() with main() function in Win32 programs
You can use standard main
in a "windows" app (that is, a GUI subsystem Windows application) even with the Microsoft tools, if you add the following to the Microsoft linker options:
/subsystem:windows /ENTRY:mainCRTStartup
Note that this is not necessary for the GNU toolchain.
Still for the Microsoft tools you can alternatively add this to your main file:
#ifdef _MSC_VER
# pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
James McNellis tells you how to get the hInstance.
Difference between WinMain,main and DllMain in C++
WinMain is used for an application (ending .exe) to indicate the process is starting. It will provide command line arguments for the process and serves as the user code entry point for a process. WinMain (or a different version of main) is also a required function. The OS needs a function to call in order to start a process running.
DllMain is used for a DLL to signify a lot of different scenarios. Most notably, it will be called when
- The DLL is loaded into the process: DLL_PROCESS_ATTACH
- The DLL is unloaded from the process: DLL_PROCESS_DETACH
- A thread is started in the process: DLL_THREAD_ATTACH
- A thread is ended in the process: DLL_THREAD_DETACH
DllMain is an optional construct and has a lot of implicit contracts associated with it. For instance, you should not be calling code that will force another DLL to load. In general it's fairly difficult function to get right and should be avoided unless you have a very specific need for it.
Breaking down WinMain's cmdLine in old style main()'s arguments
CommandLineToArgvW looks like it would be helpful here.
WinMain not called before main (C/C++ Program Entry Point Issue)
Just found this work around and kind of feel dumb.
#define main USER_Main
This then takes main out of line for being the programs entry point while still hiding the fact that anything was messed with from the user.
How can I write a Windows application without using WinMain?
You have an incorrect understanding. The difference between main and WinMain, apart from some differet initialization code, is the parameters passed to it.
main looks like this:
int main(int argc, char* argv[]);
While WinMain looks like this:
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);
Something has to setup those parameters and make the call, and that's the startup code. When you compile and link a program, one of the linker parameters is the entry point, and that will be, depending on a console or GUI app, a different bit of startup code.
You can certainly write your own startup code, just go into your visual c++ source directory and you can find the startup code, it's called crt0.c and it's in the VC\crt\src directory.
How does Qt manage to use main() for non-console applications in Windows?
Qt makes use of WinMain()
defined in qtbase/src/winmain/qtmain_win.cpp
, which subsequently calls our "fictional" int main(int argc, char *argv[])
.
P.S. You could figure out this kind of tricks by setting a breakpoint in the debugger, and looking at call stack. In Visual Studio: Menu "Debug" -> Windows -> Call Stack.
Undefined reference to WinMain (C++ MinGW)
This example code uses wWinMain
but
One thing to note is that Visual C++ supports a “wWinMain” entry point
where the “lpCmdLine” parameter is a “LPWSTR”. You would typically use
the “_tWinMain” preprocessor definition for your entry point and
declare “LPTSTR lpCmdLine” so that you can easily support both ANSI
and Unicode builds. However, the MinGW CRT startup library does not
support wWinMain, so you’ll have to stick with the standard “WinMain”
and use “GetCommandLine()” if you need to access command line
arguments.
via Building Win32 GUI Applications with MinGW
In this specific case, you can use WinMain
instead. This program doesn't use pCmdLine
value, so it should compile when you change wWinMain
to WinMain
and PWSTR pCmdLine
to PSTR pCmdLine
.
If you later would need unicode command line use LPWSTR cmd_line = GetCommandLineW();
instead of WinMain
argument.
Newer Mingw versions also support -municode
linker option switching to alternate startup code allowing to use wWinMain
instead of WinMain
(or wmain
instead of main
). Add it to your command line, linker options in IDE or makefile.
g++ other_options_and_arguments -municode
Where is WinMain() in Win32 API implemented?
The documentation for WinMain explains, what it is:
The user-provided entry point for a graphical Windows-based application.
It is declared in the SDK, but the program author is required to implement it.
When a new process is created, the OS calls into the executable image's exported entry point. By default, this is the C Runtime's (CRT) entry point (WinMainCRTStartup), that prepares the execution environment prior to transferring control to the user-provided entry point WinMain
. This is the first user-authored code that executes.
You can find more information on what is going on when when launching an executable on Windows at WinMain is just the conventional name for the Win32 process entry point.
There's also a CppCon 2018 talk by Matt Godbolt titled The Bits Between the Bits: How We Get to main(), that explains at length what's happening before the first line of user-authored code is executed. It is specific to Linux, but the principles apply to Windows as well.
Related Topics
Vectors, Structs and Std::Find
Deleting a Pointer to Const (T Const*)
How to Set the Icon For My Application in Visual Studio 2008
Templates: Parent Class Member Variables Not Visible in Inherited Class
Why Can Lambdas Be Better Optimized by the Compiler Than Plain Functions
Static Constructors in C++? I Need to Initialize Private Static Objects
Where to Put Default Parameter Value in C++
What Can Happen If Printf Is Called With a Wrong Format String
Prevent Static Initialization Order "Fiasco", C++
C++ "Cin" Only Reads the First Word
Vector Size - 1 When Size Is 0 in C++
Should the Exception Thrown by Boost::Asio::Io_Service::Run() Be Caught
Fast Ceiling of an Integer Division in C/C++
Arrays VS Vectors: Introductory Similarities and Differences