Re: error LNK2019: unresolved external symbol _main referenced in
function ___tmainCRTStartup MSVCRTD.lib Win32App
* Leigh Johnston:
* Leigh Johnston:
* Tauqir:
I am trying a very simple windows tutorial, all code is from the
tutorial but at compile time it is giving the above error. I am using
Visual Studio 2008 C++, starting with an empty project, Here is the
code:
Any ideas, where is this function _tmainCETStartup coming in from and
where should be what it is looking for?
[snip code]
Try creating the project again but this time choose "Win32 Project /
Windows Application" and not "Win32 Console Application / Console
Application".
After doing that ensure you use the following for "WinMain":
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
}
Especially important is the LPTSTR to avoid Unicode/ANSI problems
although the linker might be forgiving.
Tauqir: evidently you mistyped the name of the missing function. I presume it
was 'mainCRTStartup'.
'mainCRTStartup' is one of several Microsoft runtime library functions that can
be used as your program's entry point, where the execution starts. This
particular function calls a standard C or C++ 'main' function, which you are
supposed to define. The others call other non-standard startup functions such as
WinMain.
With Microsoft's toolchain one way to specify which entry point function to use
is to choose the right project type in Visual Studio, as Leigh advised.
Ultimately that translates down to an /entry option being passed to the linker,
or no such option (for the default). The determination of a default is intricate
and as far as I know not documented, so to take charge, when you want to do
that, you need to use /entry (it can be specified in the project settings).
Leigh: I'm certain your advise about LPTSTR is well-meant, and it is like "we
all know that" among many Windows programmers. However, it's advice that once
(early to middle 90's) was great, but which after that is wrong, perpetuated by
bad Microsoft code examples and copycat programming & teaching. It's like advice
talking about proper care of horses in order to help you drive safely to work.
First, the OP's code uses plain Unicode string like L"ouch", which means the
source will only compile with one setting of T-stuff, namely Unicode.
Secondly, supporting Windows 9x, which the T-stuff is about, is as of 2010 not
worth the effort.
Third, except when using MFC the way to go for supporting Unicode in Windows 9x
(if some evil manager requires that) is to use Microsoft's Layer for Unicode.
In short, T-stuff is just silly and adds a lot of needless work, and if one
absolutely feels that one must use a Microsoft specific startup function instead
of standard 'main', then that should be 'wMain' or 'wWinMain' (Unicode).
Here's the OP's code reworked to less Microsoft'isms, less C'isms, and without
the extremely misleading & incorrect comments:
<code>
#define STRICT
#define UNICODE
#include <windows.h>
#include <stdexcept>
bool throwX( char const s[] ) { throw std::runtime_error( s ); }
wchar_t const windowClassName[] = L"BasicApp";
wchar_t const windowTitle[] = L"A Simple Window";
LRESULT CALLBACK windowProcedure(
HWND windowHandle, UINT msg_id, WPARAM wParam, LPARAM lParam
)
{
switch( msg_id )
{
case WM_DESTROY: // Window is being destroyed.
PostQuitMessage( WM_QUIT ); // Terminates message loop.
break;
default:
return DefWindowProc( windowHandle, msg_id, wParam, lParam );
}
return 0;
}
void registerWindowClass()
{
WNDCLASSEX info = { sizeof( WNDCLASSEX ) };
info.style = CS_HREDRAW | CS_VREDRAW;
info.lpfnWndProc = windowProcedure;
info.hIcon = LoadIcon( 0, IDI_APPLICATION );
info.hCursor = LoadCursor( 0, IDC_ARROW );
info.hbrBackground = reinterpret_cast<HBRUSH>( COLOR_WINDOW + 1 );
info.lpszClassName = windowClassName;
info.hInstance = GetModuleHandle( 0 );
info.hIconSm = LoadIcon( 0, IDI_APPLICATION );
RegisterClassEx( &info ) || throwX( "RegisterClassEx failed" );
}
HWND createMainWindow()
{
HWND const handle = CreateWindow(
windowClassName,
windowTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
0,
0,
GetModuleHandle( 0 ),
0
);
handle != 0 || throwX( "CreateWindow failed" );
return handle;
}
void processMessages()
{
MSG msg;
while( GetMessage( &msg, 0, 0, 0 ) > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
void cppMain()
{
registerWindowClass();
ShowWindow( createMainWindow(), SW_SHOWNORMAL );
processMessages();
}
int main()
{
try
{
cppMain();
return EXIT_SUCCESS;
}
catch( std::exception const& )
{
return EXIT_FAILURE;
}
}
</code>
Note to OP: the GNU toolchain's linker is happy with the standard 'main' also
for a GUI subsystem application, but Microsoft's tools are geared towards more
non-standard behavior, so for a GUI subsystem app, in the project properties you
may have to specify '/entry:mainCRTStartup' (linker option).
Cheers & hth.,
- Alf