Windows API
본 시리즈에서는 Windows API 개별 함수에 대해 간략한 사용법 및 응용에 대해 정리한다.
이전 게시글: 크리티컬 섹션을 사용하여 스레드간 변수 공유
OutputDebugString을 printf처럼 서식(포맷) 적용하여 사용하기
OutputDebugString
은 Windows 응용 프로프램이 실행되는 동안 디버그 출력 채널을 통하여 테스트에 필요한 문자열을 출력할 있는 함수이다. MSDN에 따르면 그 원형은 다음과 같이 선언되어 있다.
VOID OutputDebugString(
LPCTSTR lpOutputString // string to be displayed
);
위와 같이 OutputDebugString
은 이미 완성된 문자열만을 출력할 뿐, printf
처럼 서식과 가변인수를 전달하는 기능이 없다. 때문에 변수의 값을 출력하고자 할 때 별도의 버퍼를 마련해야 하고, 유니코드 또는 MBCS 매크로에 따른 TCHAR
처리 등 매번 출력할 때마다 다소 불편한 면이 있다. 물론 MFC로 가면 TRACE
매크로가 있어서 디버그 문자열 출력 시 변수 출력과 서식 지정이 용이하지만, Windows API만을 사용하여 코딩할경우 이상하게도 마땅한 공식적인 함수가 없다.
기존 함수의 불편을 덜고, 디버그 문자열 출력 시 변수의 값 출력을 용이하게 하기 위하여 새 함수를 다음과 같이 정의할 수 있다.
#define BUFFER_CONST 8192 // 내부 버퍼의 크기 (필요한만큼 조정 가능)
VOID OutputFormattedDebugString(LPCTSTR format, ...) {
static TCHAR buffer[BUFFER_CONST] = { TEXT('\0'), }; // TCHAR형 문자 버퍼
va_list arg; // 가변인수 벡터
va_start(arg, format); // 가변인수 벡터 리셋
_vstprintf(buffer, format, arg);
va_end(arg);
OutputDebugString(buffer);
ZeroMemory(buffer, sizeof(buffer)); // 사용 후 버퍼 내용 지우기
}
이 함수의 작동은 비교적 간단한 편이다. 임시 버퍼에 서식대로 문자열을 출력하여 완성된 문자열을 얻고, 이것을 다시 OutputDebugString
에 전달하는 것이다.
Windows API는 문자형으로 TCHAR
를 사용한다. 임시 버퍼로 문자열을 출력할 때 이를 고려하여 함수를 선택할 필요가 있다.
printf
는 지정된 서식을 따라 표준 출력에 문자열을 출력하는 함수이다. 이 함수의 와이드 문자 버전은 wprintf
이다. printf
와 wprintf
를 TCHAR
형으로 일반화한 명칭이 _tprintf
이다.
/* stdio.h */
int printf(const char *format [, argument]... );
/* wchar.h */
int wprintf(const wchar_t *format [, argument]... );
/* tchar.h */
#ifdef _UNICODE
#define _tprintf wprintf
#else
#define _tprintf printf
#endif
sprintf
는 지정된 서식을 따라 특정한 버퍼에 문자열을 출력하는 함수이다. 이 함수의 와이드 문자 버전은 swprintf
이다. sprintf
와 swprintf
를 TCHAR
형으로 일반화한 명칭이 _stprintf
이다.
/* stdio.h */
int sprintf( char *buffer, const char *format [, argument] ... );
/* wchar.h */
int swprintf( wchar_t *buffer, const wchar_t *format [, argument] ... );
/* tchar.h */
#ifdef _UNICODE
#define _stprintf swprintf
#else
#define _stprintf sprintf
#endif
printf
, sprintf
는 가변인수를 하드코딩으로 받는 함수이다. 서식과 가변인수가 몇 개가 있든, 동적으로 문자열을 출력하기 위하여 가변인수 벡터로 가변인수를 받는 함수가 vprintf
와 vsprintf
이다. 각각 표준 출력과 특정한 버퍼에 완성된 문자열을 출력한다.
vprintf
의 와이드 문자 버전은 vwprintf
이고, vprintf
와 vwprintf
를 TCHAR
형으로 일반화한 명칭이 _vtprintf
이다. 마찬가지로 특정 버퍼로 문자열을 출력하는 함수는 vsprintf
, vswprintf
이고 이를 일반화한 명칭이 _vstprintf
이다. 본 함수에서 _vstprintf
를 사용한 이유는 이와 같다.
/* stdio.h */
int vprintf( const char *format, va_list argptr );
int vsprintf( char *buffer, const char *format, va_list argptr );
/* wchar.h */
int vwprintf( const wchar_t *format, va_list argptr );
int vswprintf( wchar_t *buffer, const wchar_t *format, va_list argptr );
/* tchar.h */
#ifdef _UNICODE
#define _vtprintf vwprintf
#define _vstprintf vswprintf
#else
#define _vtprintf vprintf
#define _vstprintf vsprintf
#endif
사용 방법은 printf
와 다르지 않다. 서식을 첫 번째 인수에 넣고, 다음 인수부터는 0개 이상의 변수들을 전달하면 된다. 다음은 그 예이다.
VOID OutputFormattedDebugString(LPCTSTR format, ...); // 새롭게 정의한 함수 원형
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
OutputFormattedDebugString(TEXT("Hello, World!\n")); // 일반 문자열 출력 테스트
OutputFormattedDebugString(TEXT("%d + %d = %d\n"), 1, 2, 1 + 2); // 가변인수를 통한 값 출력 테스트
OutputFormattedDebugString(TEXT("string: \"%s\"\n"), TEXT("DebugString")); // 문자열 서식 테스트
OutputFormattedDebugString(TEXT("character: '%c'\n"), TEXT('A')); // 문자 서식 테스트
return 0;
}
소스 코드를 디버그하였을 때 출력 창에 의도대로 출력된 것을 확인할 수 있다.