API WinMain

IT/개발공부 / / 2020. 9. 3. 00:14
728x90
반응형

tWinMain

윈도우 API 예제를 만들어보겠습니다.  프로그램의 시작점인 엔트리 포인트 함수를 분석해 보고자 합니다.

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

int WINPAI_tWinMain( HINSTANCE hinst, HINSTANCE hPrev,
                     LPTSTR IpCmdLine, int nShowCmd)
                     
{
           MessageBox(0, TEXT("Hello,API"), TEXT("First"), MB_OK)
           return 0;
}

// winMain함수

 

헤더 파일

첫 행을 보면 windows.h 가 인클루드 되어 있습니다. 하나의 헤더 파일에 모든 API 함수둘의 원형과 사용하는 상수들이 정의가 되어 있기 때문에 windows.h 만 포함하면 됩니다. 물론 특별한 경우에는 해당하는 헤더 파일을 포함해야 하지만 예제 수준에서는 windows.h 만 포함하면 거의 문제가 없습니다.

 

Windows.h 파일은 기본적으로 데이터 타입, 함수 원형, 매크로 상수등을 정의하며 그 외 윈도우 프로그래밍에 필요한 보조 헤더 파일을 포함하고 있습니다.

 

tchar.h 파일은 앞 장에서 말한 대로 범용타입을 사용하기 위한 헤더입니다.

 

시작점

윈도우 프로그램에서의 엔트리 포인트 함수는 환경에 따라 다양한 키워드가 사용될 수 있습니다.

 

엔트리 포인트 함수 내용
WinMain 유니코드가 아닌 환경
wWinMain 유니코드 환경
_tWinMain 매크로이며 범용적인 형태

 

각 환경에 맞는 엔트리 포인트 함수를 사용해야 하며 이것이 제대로 해결 되지 않을 시 아래와 같은 링크 에러가 발생합니다. (참조 위치 : __tmainCRTStartup 함수)에서 확인하지 못했습니다.

 

함수명 앞에 있는 WINAPI 지정자는 윈도우의 표준 호출 규약인 __stdcall을 사용한다는 의미입니다.

//minwindef.h

#define WINAPI __stdcall

 

리턴 타입과 인자

인자 의미
hInstance 프로그램의 인스턴스 핸들
hPrev 바로 앞에 실행된 현재 프로그램의 인스턴스 핸들, 없을 경우는 NULL이며 Win32에서는 항상 NULL 입니다.
IpCmdLine 명령행으로 입력된 프로그램 인자입니다.
nShowCmd 프로그램이 실행될 형태이며, 최소화, 보통, 최대화 모양 등이 전달됩니다.

API 함수들 중 HINSTANCE 타입을 요구하는 경우가 있습니다. 우선 HINSTANCE란 프로그램 자체를 일컫는 정수값이며 응용 프로그램의 인스턴스핸들이라고 표현할 수 있습니다. 프로그램 내부에서 자기 자신을 가리키는 1인칭 대명사입니다. 실제 타입은 void* 형태로 되어 있으며 아래 함수를 통해 얻어 올 수 있습니다.

HINSTANCE hCurInst = GetModuleHandle(0);

 

MessageBox 함수

1번째 피라미터는 윈도우의 핸들, 2번째 피라미터는 메시지 출력 내용, 3번째 피라미터는 타이틀바 문자열, 4번째 피라미터는 버튼의 모양 및 ICON 모양을 나타내며 winapifamily.h 파일에 정의되어 있습니다.

#include <winapifamily.h>


#define MB_OK 0x00000000L
#define MB_OKCANCEL 0x00000001L
#define MB_ABORTRETRYIGNORE 0x00000002L
#define MB_YESNOCANCEL 0x00000003L
#define MB_YESNO 0x00000004L
#define MB_RETRYCANCEL 0x00000005L
#if(WINVER >= 0x0500)
#define MB_CANCELTRYCONTINUE 0x00000006L
#endif

#define MB_ICONHAND 0x00000010L
#define MB_ICONQUESTION 0x00000020L
#define MB_ICONEXCLAMATION 0x00000030L
#define MB_ICONASTERISK 0x00000040L

 

함수 호출 규약

일반적으로 하나의 함수를 어떻게 컴파일 되도록 하느냐에 따른 호출 규약이 있습니다. 몇가지만 살펴보면

 

호츌 규약 인자 전달 스택 제거 기타
 __cdecl Right -> Left 호출자가 인자 제거 C/C++ 함수의 기본 호출 규약 
__stdcall Right -> Left 호출된 함수가 인자 제거 대부분의 System 함수가 사용
this Right -> Left 호출자가 인자 제거 C++ 클래스의 맴버 함수가 사용

__stdcall은 윈도우 프로그램에서 사용하는 대부분의 API가 사용하는 방식입니다. __cdecl과의 차이점은 호출된 함수가 스택에서 인자를 제거한다는겁니다. 이러한 이유 때문에 __cdecl 방식보다 메모리 사용이 효율적입니다. Pascal 언어가 사용하던 방식이라서 Pascal 호출 규약이라고도 합니다.

 

대다수의 윈도우 프로그램에서 사용하는 함수는 __stdcall 방식을 사용합니다. WINAPI, CALLBACK, APIENTRY 등의 매크로는 __stdcall 방식의 매크로입니다.

 

exe 타입

비주얼 스튜디오를 사용하여 프로젝트를 만들 때 일반적으로 2가지 방식을 사용합니다. 1번째는 윈도우 프로그래밍을 위한 Win32 프로젝트이고 2번째는 콘솔 프로그래밍을 위한 Win32 콘솔 응용프로그램입니다. 생성된 프로젝트의 차이점은 어떠한 하위 시스템을 선택하느냐에 따른 부분이고 그 외 차이점은 없습니다. 비주얼 스튜디오에서 생성된 프로젝트의 하위 시스템을 변경할 수 있는데 .exe 파일을 실행하는 방법을 지시할 수 있습니다. 그리고 선택한 하위 시스템에 따라 링커가 선택하는 진입점 기호가 결정되게 됩니다.

CUI(Console User Interface) - Win32 콘솔 응용프로그램

  • Entry Point 수행 전 Console 창이 실행됩니다.
  • Entry Point 함수는 main() 또는 wmain() 입니다.
  • Link Option 은 /SUBSYSTEM:CONSOLE 입니다.

GUI(Graphic User Interface) - Win32 프로젝트

  • Entry Point 수행 전 Console 창이 생성되지 않습니다.
  • Entry Point 함수는 WinMain(), wWinMain() 입니다.
  • Link Option은 /SUBSYSTEM:WINDOWS 입니다.

따라서 프로젝트를 목적과 다르게 생성한 경우는 속성 페이지에서 하위 시스템을 변경해야 됩니다. 또 다른 방법으로는 아래와 같은 코드 상단에 전처리 구문을 사용하여 변경할 수 있습니다.

#pragma comment (linker, "/subsystem:windwos")
#pragma comment (linker, "/subsystem:console")

 

데이터 타입

API에서 사용되는 타입들은 아래와 같이 대부분 대문자로 구성되어 있습니다.

// windef.h

typedef struct tagPOINT
{
 LONG x;
 LONG y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;

 

사용되는 특정 문자의 의미를 알면 타입을 구별하기 쉽습니다.

키워드 내용
P Pointer를 나타냅니다.
LP Win32에서 L 키워드는 의미가 없습니다.
PSTR 과 LPSTR 은 동일한 타입입니다.
T, t 범용 타입입니다. LPSTR(char*) 과 LPTSTR(TCHAR*) 는 다릅니다.
W Unicode Type입니다.
C const를 의미합니다. LPCTSTR
STR 문자열을 의미합니다. PSTR(char*)
H 객체의 핸들을 의미합니다. HWND, HPEN

 

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기