in 소프트웨어 개발

윈도우 API – 메인 함수들

http://zetcode.com/gui/winapi/main/

이 파트에서는 메인 함수들에 대해 얘기해본다.

main() 함수는 C 프로그램의 입구다. 하지만 이것은 처음 실행되는 프로그램은 아니다. 입구가 main() 인 동안에, 프로그램은 실제로는 mainCRTStartup() 안에서 호출된다. 이 함수는 C 런타임 라이브러리에 있다. 이것은 메모리 매니저, 파일 I/O 지원, 그리고 argv 파라미터를 초기화 한다. 그이후 mainCRTStartup() 함수는 main 함수를 호출할 것이다.
int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);

이들 함수는 main() 함수의 프로토타입이다-고전 콘솔 프로그램을 위한

classic_console.c

#include<stdio.h>

int main(void) {
puts(“This is a classic C program”);
return 0;
}

위의 소스 코드는 고전 콘솔 C 프로그램의 예제다.

C:\Users\Jano\Documents\Pelles C Projects\ClassicConsole>ClassicConsole.exe
This is a classic C program.

이것은 ClassicConsole.exe 프로그램의 출력이다.

wamin 함수 프로토타입

이전의 main 함수 프로토타입들은 ASCII 문자들만 받을 수 있었다. 프로그램이 확장 문자(wide character)를 커맨드 라인으로 부터 받기 위해서는, 우리는 wmain() 함수 프로토타입들을 사용해야 한다.

int wmain(void);
int wmain(int argc, wchar_t **argv);
int wmain(int argc, wchar_t *argv[]);

위의 wmain() 함수 프로토타입들은 wchar_t 문자를 커맨드라인에서 받는다. 이러한 프로토타입들을 사용하면, wmainCRTStartup() 이라는 함수 내부에서 실행이 시작된다. wmainCRTStartup()은 이후 wmain() 함수를 호출한다.

win_console.c

#include <windows.h>
#include <wchar.h>

int wmain(int argc, wcahr_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;
}

우리는 확장 문자를 받는 wmain() 함수를 만들었다. 이 예제는 콘솔 프로그램의 첫번째 입력을 출력한다. Pelles C 에 커맨드라인 입력을 삽입하기 위해서, 우리는 프로젝트 옵션에서 일반 탭에 가야 한다. 그곳에 커맨드 라인 입력들 이라는 편집 박스가 있다.

int wmain(int argc, wchar_t **argv) {

wmain() 함수의 두번째 매개변수의 타입인 wchar_t 타입에서 프로그램 입력이 확장문자임을 알려준다.

HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);

GetStdHandle() 함수는 표준 출력 standard output에 핸들을 반환해준다.

if(std == INVALID_HANDLE_VALUE) {
wprintf(L”Cannot retrieve standard output handle\n (%d)”, GetLastError());
}

이 경우의 에러에서, 우리는 INVALID_HANDLE_VALUE 리턴 코드를 받았다. 이러한 상황에서 우리는 에러 메세지를 출력한다. GetLastError() 함수는 마지막 에러 코드 값을 가져온다.

WriteConsoleW(std, argv[1], wcslen(argv[1]), cChars, NULL);

우리는 WriteConsoleW() 함수를 콘솔에서 확장 문자를 작성하기 위해 사용한다.

CloseHandle(std);

CloseHandle() 함수는 표준 출력으로 열려있는 핸들을 종료한다.

C:\Users\Jano\Documents\Pelles C Projects\WindowsConsole>WindowsConsole.exe компилятор
компилятор

우리는 러시아 단어 (컴파일러) 를 프로그램의 매개변수로 넣었다. 이 프로그램은 간단히 파라미터를 콘솔로 다시 출력할 뿐이다. 주의할 점은, 문자가 정확히 보이도록, 우리는 콘솔의 기본 폰트를 Lucida Console 로 변경해야 한다는 것이다. 우리는 확장 문자를 제대로 표현하기 위해 트루 타입 폰트가 필요하다.

_tmain 함수 프로토타입

_tmain() 함수는 마이크로소프트 확장이다. 이것은 프로그래머가 쉽게 ANSI 와 UNICODE 둘다 자신의 프로그램에 만들 수 있게 해준다. 이것은 wmain() 이나 main() 으로 변환되는 C 매크로이다. _UNICODE 상수가 정의되있든 아니든 상관없이. 과거에는 ANSI 와 UNICODE 빌드 둘다 만드는게 일반적이었다. 최근에는 많은 프로그래머들이 UNICODE 프로그램만을 만들기를 추천한다. 이것 또한 우리의 튜토리얼에서 진행할 내용이다. 우리는 대부분 유니코드 프로그램을 만들것이다.

int _tmain(void);
int _tmain(int argc, TCHAR **argv);
int _tamin(int argc, TCHAR *argv[]);

이들은 _tmain 함수 프로토타입들이다. TCHAR 매크로는 char 이나 wchar_t 로 변환될 수 있다. 이들은 UNICODE 상수에 따라 제어된다.

tmain_ex.c

#define _UNICODE
#define UNICODE

#include <windows.h>
#include <tchar.h>

int _tmain(int argc, TCHAR *argv[]) {
PDWORD cChars = NULL;
HADNLE std = GetStdHandle(STD_OUTPUT_HANDLE);

if (std == INVALID_HANDLE_VALUE) {
_trpintf(L”Cannot retrieve standard handle\n (%d)”, GetLastError());
}

if (argv[1]) {
WriteConsole(std, argv[1], _tcslen(argv[1]), cChars, NULL);
}

CloseHandle(std);

return 0;
}

이 예제는 만약 가능하다면 첫 입력을 출력한다.

#define _UNICODE
#define UNICODE

여기서 우리는 두 상수를 정의했다. 이들 정의가 의미하는 바는, 우리가 유니코드 프로그램을 빌드할거라고 하는 것이다. 이들은 C 매크로들-C런타임에 있는- 과 Windows 헤더 파일을 번역한다. _UNICODE 상수는 C runtime 의 매크로들을 번역한다. (이들 매크로들은 언더스코어와 함께 시작한다) UNICODE 상수는 Windows 해더 파일들을 번역한다.

#include <windows.h>

우리는 TCAHR 매크로의 정의를 포함했다. 이 매크로는 UNICODE 상수에 영향을 받는다.

#include <tchar.h>

우리는 반드시 이 헤더 파일을 _tmain 과 _tcslen 매크로들을 위해 포함 해야 한다. 이들은 _UNICODE 상수에 의존하여 번역된다.

int _tmain(int argc, TCHAR *argv[]) {

이 t_main() 함수는 우리의 경우에는 wmain() 이라고 번역되며, TCHAR 매크로는 wchar_t 로 번역된다.

WriteConsole(std, argv[1], _tcslen[1], cChars, NULL);

WriteConsole() 매크로는 WriteConsoleW() 함수로 번역된다. WriteConsoleW() 는 콘솔에 출력을 쓴다. _tcslen 매크로는 wcslen() 함수로 번역된다; 이것은 확장 문자열의 길이를 반환한다.

C:\Users\Jano\Documents\Pelles C Projects\TMainEx>TMainEx.exe “операционная система”
операционная система

이 프로그램은 또 다른 러시아어 단어 (운영체제) 를 매개변수로 받고 콘솔에 출력한다.

WinMain 함수 프로토타입들

여기까지 콘솔 main 함수들을 봤다. 시각적인 유저 인터페이스 개발을 위해서는, 우리는 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);

이들 세개의 함수 프토토타입들은 윈도우 GUI 어플리케이션의 입구이다. wWinMain() 함수의 pCmdLine 매개변수는 유니코드 문자열로서의 커맨드 라인 입력을 가진다. WinMain() 함수의 pCmdLine 매개변수는 ANSI 문자열로서 커맨드 라인 입력을 가진다. _tWinMain 은 C 매크로인데 다른 두개의 함수 프로토타입으로 번역된다- _UNICODE 상수가 정의되 있냐에 따라서.

WinMain()이 입구일때, 프로그램의 실행은 WinMainCRTStartup() 에서 시작된다. wWinMain()의 경우, 실행은 wWinMainCRTStartup() 에서 시작된다.

winmain_ex.c

int WINAPI wWinMain(HINSTANCE hInstacne, HINSTACNE hPrevInstacne, PWSTR szCmdLine, int CmdShow) {

MessageBoxW(NULL, szCmdLine, L”Title”, MB_OK);

return 0;
}

이 코드는 화면에 작은 메세지 박스를 띄운다. 이것은 첫 커맨드라인 입력을 표시한다.

int WINAPI wWinMain(HINSTACNE hInstacne, HINSTACNE hPrevInstance, PWSTR szCmdLine, int CmdShow)

wWinMain() 함수의 세번째 매개변수는 PWSTR (pointer to wide string; 확장 문자로의 포인터) 이다. 이것은 확장 문자를 받는다.

그림: 매세지 박스

윈도우 API 튜토리얼의 이번 파트에서는, 메인 함수들을 살펴보았다.