V tretej časti seriálu o Windows API budeme hovoriť o funkčných prototypoch main. Funkčný prototyp je tvorený názvom funkcie a typom signatúry, pričom sa vynecháva telo funkcie.
Prototypy main
Funkcia main() je vstupom do programu v jazyku C. Nie je však prvým kódom, ktorý sa spustí. V skutočnosti sa ako prvá zavolá funkcia mainCRTStartup(), ktorá sa nachádza v C runtime knižnici. Táto funkcia inicializuje manažéra pamäte, podporu súborového vstupu a výstupu a parameter argv. Po skončení týchto úkonov sa volá funkcia main() nášho programu.
int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);
Toto sú funkčné prototypy pre main() funkciu v klasickom konzolovom programe.
#include <stdio.h>
int main(int argc, char **argv) {
puts("This is a classic C program.");
return 0;
}
Predchádzajúci výpis je ukážkou klasického konzolového programu v jazyku C.
C:\winapi\main\ClassicConsole >ClassicConsole.exe
This is a classic C program.
Toto je výstup programu, ktorý sme nazvali ClassicConsole.exe.
Prototypy wmain
Predchádzajúce prototypy main funkcií mohli prijímať iba ASCII znaky. Ak chceme pracovať so širokými znakmi, musíme použiť funkčné prototypy wmain.
int wmain(void);
int wmain(int argc, wchar_t **argv);
int wmain(int argc, wchar_t *argv[]);
Tieto funkčné prototypy wmain prijímajú wchart_t znaky z príkazovej riadky. Ak použijeme tieto prototypy, tak sa beh nášho programu začne funkciou wmainCRTStartup(), ktorá neskôr zavolá funkciu wmain().
#include <windows.h>
#include <wchar.h>
int wmain(int argc, wchar_t **argv) {
PDWORD cChars = NULL;
HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
if (std == INVALID_HANDLE_VALUE) {
wprintf(L"Cannot retrieve standard output handle\n (%d)",
GetLastError());
}
if (argv[1]) {
WriteConsoleW(std , argv[1], wcslen(argv[1]), cChars , NULL);
}
CloseHandle(std);
return 0;
}
Máme wmain() funkciu, ktorá prijíma široké znaky. V príklade sa vypíše prvý argument konzolového programu. Argumenty príkazového riadku pridáme v Pelles C tak, že pôjdeme do Project options a zvolíme záložku General tab. Máme tam editovateľný box nazvaný Comman line arguments. Doňho vpíšeme argumenty.
int wmain(int argc, wchar_t **argv) {
Typ wchar_t druhého parametra funkcie wmain() nám hovorí, že program prijíma input v širokých znakoch.
HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
Funkcia GetStdHandle() vracia handle štandardného výstupu.
if (std == INVALID_HANDLE_VALUE) {
wprintf(L"Cannot retrieve standard output handle\n (%d)",
GetLastError());
}
V prípade, že dôjde ku chybe dostaneme návratový kód INVALID_HANDLE_VALUE. Ak dôjde k takejto situácii, vypíšeme chybovú hlášku na konzolu. Funkcia GetLastError() vracia kód poslednej chyby.
WriteConsoleW(std , argv[1], wcslen(argv[1]), cChars, NULL);
Pomocou funkcie WriteConsoleW() vypíšeme text obsahujúci široké znaky na konzolu. Na konzolu vypisujeme prvý argument príkazového riadku.
CloseHandle(std);
Funkciou CloseHandle uzavrieme otvorený handle štandardného výstupu.
C:\winapi\main\WindowsConsole>WindowsConsole.exe čepeľ
čepeľ
Nášmu programu, ktorý sme si nazvali WindowsConsole.exe, dáme ako parameter slovenské slovo čepeľ. Program vypíše parameter späť na konzolu. Pre správne fungovanie programu potrebujeme zmeniť písmo konzoly vo Windows na Lucida Console. Na korektné zobrazenie širokých znakov potrebujeme písmo true type.
Prototypy _tmain
_tmain() je rozšírením firmy Microsoft. Umožňuje naraz vytvárať ANSI a UNICODE verzie programov. Je to makro, ktoré sa preloží na wmain() alebo main() funkciu v závislosti od toho, či bola definovaná konštanta _UNICODE. Kedže operačné systémy Windows 98 a skoršie neumožňovali vytvárať UNICODE verzie, bolo bežné kvôli kompatibilite so staršími verziami Windows vytvárať dve rôzne verzie programov. V súčastnosti sa jedná o prežitok; dnes sa vytvárajú predovšetkým Unicode verzie programov.
int _tmain(void);
int _tmain(int argc, TCHAR **argv);
int _tmain(int argc, TCHAR *argv[]);
Toto sú funkčné prototypy _tmain(). Makro TCHAR sa preloží buď na char alebo wchar_t. To sa riadi konštantou UNICODE.
#define _UNICODE
#define UNICODE
#include <windows.h>
#include <tchar.h>
int _tmain(int argc, TCHAR *argv[]) {
PDWORD cChars = NULL;
HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
if (std == INVALID_HANDLE_VALUE) {
_tprintf(L"Cannot retrieve standard output handle\n (%d)",
GetLastError());
}
if (argv[1]) {
WriteConsole(std, argv[1], _tcslen(argv[1]), cChars, NULL);
}
CloseHandle(std);
return 0;
}
Program vypíše svoj prvý argument, ak existuje.
# define _UNICODE
# define UNICODE
Definujeme dve konštanty. Tieto definície znamenajú, že ideme vytvárať Unicode program. Transformujú makrá v C runtime a Windows hlavičkových súboroch. Konštanta _UNICODE preloží makrá v C runtime; tieto makrá sa začínajú podtržníkom. Konštanta UNICODE preloží makrá vo Windows hlavičkových súboroch.
#include <windows.h>
Vkladáme definíciu makra TCHAR. Preklad tohto makra závisí od konšanty UNICODE.
#include <tchar.h>
Tento hlavičkový súbor potrebujeme kvôli makrám _tmain, _tcslen, a _tprintf. Tie sú preložené v závislosti od makra _UNICODE.
int _tmain(int argc , TCHAR *argv[]) {
V našom prípade sa _tmain() preloží na wmain() a TCHAR na wchar_t.
WriteConsole(std, argv[1], _tcslen(argv [1]), cChars, NULL);
Makro WriteConsole() sa preloží na funkciu WriteConsoleW(). Funkcia vypíše reťazec na konzolu. Makro _tcslen sa transformuje na funkciu wcslen(), ktorá vracia dĺžku reťazca so širokými znakmi.
C:\winapi\main\TMainEx>TMainEx.exe žriebä
žriebä
Program prijíma slovenské slovo žriebä ako parameter a vypíše ho na konzolu.
Prototypy WinMain
Doteraz sme preberali prototypy pre konzolové aplikácie. Pre aplikácie s grafickým rozhraním používame funkčné prototypy WinMain.
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR pCmdLine, int nCmdShow);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow);
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow);
Tieto tri funkčné prototypy sú vstupnými bodmi pre Windows GUI aplikácie. Parameter pCmdLine funkcie wWinMain() prijíma argumenty vo forme Unicode reťazcov. Parameter pCmdLine funkcie WinMain() prijíma argumenty vo forme ANSI reťazcov. Macro _tWinMain sa preloží buď na WinMain() alebo wWinMain() v závislosti od toho, či bola definovaná konštanta _UNICODE. Ak je vstupným bodom WinMain(), beh programu sa začne v WinMainCRTStartup(), v prípade wWinMain() je to wWinMainCRTStartup().
#include <windows.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR szCmdLine, int CmdShow) {
MessageBoxW(NULL, szCmdLine, L"Title", MB_OK);
return 0;
}
Tento program ukáže malý box na obrazovke. Zobrazí prvý argument z príkazovej riadky.
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR szCmdLine, int CmdShow)
Tretí parameter funkcie wWinMain() má typ PWSTR, čo je pointer na široký znak. Tento parameter prijíma široké znaky.
Záver
V tomto článku sme rozoberali rôzne druhy prototypov funkcie main. Zvlášť pre konzolové a pre GUI aplikácie. Boli použité materiály z autorovho e-booku a tutoriálu.