error LNK2019: unresolved external symbol _main referenced infunction ___tmainCRTStartup MSVCRTD.lib

T

Tauqir

Hi,
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?

#include <windows.h>

LPCTSTR ClsName = L"BasicApp";
LPCTSTR WndName = L"A Simple Window";

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam);

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG Msg;
HWND hWnd;
WNDCLASSEX WndClsEx;

// Create the application window
WndClsEx.cbSize = sizeof(WNDCLASSEX);
WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
WndClsEx.lpfnWndProc = WndProcedure;
WndClsEx.cbClsExtra = 0;
WndClsEx.cbWndExtra = 0;
WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClsEx.lpszMenuName = NULL;
WndClsEx.lpszClassName = ClsName;
WndClsEx.hInstance = hInstance;
WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

// Register the application
RegisterClassEx(&WndClsEx);

// Create the window object
hWnd = CreateWindow(ClsName,
WndName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);

// Find out if the window was created
if( !hWnd ) // If the window was not created,
return 0; // stop the application

// Display the window to the user
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);

// Decode and treat the messages
// as long as the application is running
while( GetMessage(&Msg, NULL, 0, 0) )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return Msg.wParam;
}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
// If the user wants to close the application
case WM_DESTROY:
// then close it
PostQuitMessage(WM_QUIT);
break;
default:
// Process the left-over messages
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
// If something was not done, let it go
return 0;
}
 
A

Alf P. Steinbach

* 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
 
T

Tauqir

* Leigh Johnston:




* Leigh Johnston:
[snip code]
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- Hide quoted text -

- Show quoted text -

Guys, Thanks very much,
I started with the Win32Project / Windows application and of course
the startup project does give me a working starting point with
_tWinMain as the windows APIENTRY point.
Interestingly Unicode is at the core of my work. Purpose is to make a
simplest unicode editor for my native language,'Urdu'. A lot of people
type Urdu in English script and I just cannot stand it.
I initailly started with C Sharp, but was unable to get the client
area where users encoded strings will be displayed. Only option was to
use the Rich Text control, but that was rather limiting, because it
had to be on a form.
Now my challenge is to read user input (c=getchar()? )- based on a
keyboard mapping - encode the character in Urdu and display
(putchar(c) )it in the Arial Unicode MS, which is shipped with Windows
XP. No Windows 98 consideration.
My C++ skills are at this moment rusted. A few lines of code to get
this done will be a great boost at this time.

Tauqir
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top