[C++] Statyczna metoda klasy jako punkt wejścia aplikacji w C++

W tym wpisie chciałem napisać o pewnej właściwości linkera MS – punktem wejścia aplikacji może być dowolna funkcja o odpowiedniej sygnaturze – w tym także statyczna metoda klasy! W przypadku aplikacji okienkowej i wykorzystaniu Unicode odpowiednia sygnatura sygnatura wygląda tak

int __stdcall EntryPt(
     HINSTANCE hInstance, 
     HINSTANCE hPrevInstance,
     WCHAR* lpCmdLine,
     int nCmdShow)

Wystarczy poinformowac o tym linker. W przypadku produktu Microsoftu

link ${OBJS} /SUBSYSTEM:WINDOWS  /ENTRY:EntryPt ${LIBS}

Jak już wspomniałem punktem wejścia może być statyczna metoda klasy

struct WinApp {
     static int __stdcall wWinMain(
          HINSTANCE hInstance, 
          HINSTANCE hPrevInstance,
          WCHAR* lpCmdLine,
          int nCmdShow);
}

Oto mały przykład okienkowej aplikacji Win32 której punktem wejścia jest statyczna metoda metoda klasy

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/**
cl -c winapp.cpp

link  winapp.obj /SUBSYSTEM:WINDOWS  /ENTRY:WinApp::wWinMain  kernel32.lib user32.lib gdi32.lib
**/
struct WinApp {
    static int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, WCHAR* lpCmdLine, int nCmdShow);
    static LRESULT __stdcall WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};



int WINAPI WinApp::wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, WCHAR* lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc = { 
        sizeof(WNDCLASSEX), CS_CLASSDC, WinApp::WndProc, 0L, 0L, 
        GetModuleHandle(NULL), NULL,
        LoadCursor( NULL, IDC_ARROW ), 
        ( HBRUSH )( COLOR_WINDOW ), NULL,
        "WinApp", NULL };
    RegisterClassEx( &wc );
    HWND hWnd = CreateWindow(
        "WinApp",
        "«Jarosław Przygódzki» Statyczna metoda klasy jako punkt wejścia aplikacji w C++",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
        GetDesktopWindow(), NULL, wc.hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);
    MSG msg = {0};
    while( GetMessage(&msg, NULL, 0, 0 ))
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    return 0;
}

LRESULT __stdcall WinApp::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{
    switch(uMsg) {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0L;
}

Proces kompilacji i linkowania nie jest skomplikowany

cl -c winapp.cpp
link winapp.obj /SUBSYSTEM:WINDOWS /ENTRY:WinApp::wWinMain kernel32.lib user32.lib
PS

CALLBACK i WINAPI to właśnie aliasy na konwencję wywołania __stdcall

// WinDef.h
#define CALLBACK    __stdcall
#define WINAPI      __stdcall

Deklaracje mogą więc wyglądać następująco

struct WinApp {
     static int WINAPI wWinMain(
          HINSTANCE hInstance, 
          HINSTANCE hPrevInstance,
          WCHAR* lpCmdLine,
          int nCmdShow);
    static LRESULT CALLBACK WndProc(
         HWND hWnd,
         UINT uMsg, 
         WPARAM wParam, 
         LPARAM lParam)
}

I najczęściej tak właśnie wyglądają.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s