안녕하세요. 오늘은 MFC 상에서 CString, TCHAR, char* 문자열 간의 변환 방법과 관련된 디버깅 과정을 이야기 해 보겠습니다. 컴퓨터 비전에 관심이 있어서 OPENCV 를 이용 하여 프로그래밍을 시도 해 보고 있습니다. (오픈소스 OPENCV를 이용한) 컴퓨터 비전 실무 프로그래밍 도서를 보고 있는데요, 구현 중 아래의 코드를 만났습니다.

char *getFileDialog()
{
    char *readFileName = (char*)NULL;
 
    char szFilter[] = "지원 영상 파일(*.bmp, *.jpg, *.gif, *.png, *.tif)|*.bmp;*.jpg;*.gif;*.png;*.tif||";
    printf("\n");
    printf("\t * 파일 대화상자를 이용하여 영상 파일을 선택하십시오. \n\n");
    printf("\t\n");
 
/*10행*/ CFileDialog fileDlg(TRUE, NULL, NULL, OFN_EXPLORER | OFN_HIDEREADONLY, szFilter);
 
    if(fileDlg.DoModal() == IDOK)
/*13행*/ readFileName = (char*)strdup((char*)(LPCTSTR)fileDlg.GetPathName());
 
    return readFileName;
}

10 행과 13 행에서 에러가 나타나서, 5 행과 13 행을 아래와 같이 수정 하였습니다.

char *getFileDialog()
{
    char *readFileName = (char*)NULL;
 
/*5행*/ CString szFilter = _T("지원 영상 파일(*.bmp, *.jpg, *.gif, *.png, *.tif)|*.bmp;*.jpg;*.gif;*.png;*.tif||");
    printf("\n");
    printf("\t * 파일 대화상자를 이용하여 영상 파일을 선택하십시오. \n\n");
    printf("\t\n");
 
    CFileDialog fileDlg(TRUE, NULL, NULL, OFN_EXPLORER | OFN_HIDEREADONLY, szFilter);
 
    if(fileDlg.DoModal() == IDOK)
/*13행*/ readFileName = strdup(CT2A(fileDlg.GetPathName()));
 
    return readFileName;
}

5 행 : 10 행의 szFilter 자리에는 LPCTSTR 형이 인자로 입력되어야 합니다. 그런데 LPCTSTR 자리에 char* 를 입력하니 에러가 나게 됩니다. 따라서 5행의 char* 자료형을 CString 으로 바꿔 줍니다.

13 행 : GetPathName() 은 CString 을 반환 합니다. 이를 char* 형식인 readFileName 에 복사하기 위해 strdup, CT2A 를 이용 합니다. 링크 CString char* 변환 를 보면, 책의 코드 13행의 (char*)(LPCTSTR) 는 멀티바이트 환경에서만 사용 가능함을 알 수 있습니다.


참고

char*, LPCTSTR, TCHAR 의 차이

유니코드에서 CString to char* 로 바꾸는 방법

CT2A 매크로의 종류

strdup() 문자열의 clone 만들기


결국 CString, TCHAR, char* 의 개념과 서로의 변환 방법만 알고 있었다면 쉽게 해결할 수 있는 문제였습니다. 그러나 C++, MFC 를 처음 접하는 내가 이 에러를 고치기는 쉽지 않았습니다. 아마도 제가 그동안 고수준 언어에만 익숙해져 있었기 때문일 것입니다. 문자열 처리와 같이 까다로운 작업들을 '알아서' 해 주는 언어에만 익숙하다 보니,직접 문자열 변환을 해야 하는 상황에서 에러가 발생하자 원인조차 파악하지 못했던 것입니다. 항상 누군가가 '알아서' 해 주기만을 바란 것은 아닌지...


참고로 Project Property 에서 Character Set 을 Unicode 가 아니라 Multi-Byte 로 설정 해 놓으면 책의 코드도 정상작동 합니다. 그러나 이는 Visual 2005 이전에 쓰던 코드이고, 현재(그리고 이후에)는 유니코드를 사용하는 추세이므로 Multi-Byte 로 설정하기 보다는 Unicode 를 지원할 수 있도록 코딩하는 습관을 들이는 것이 좋을 것 같다는 것이 제 생각입니다.