마이그레이션 중.. #include<Windows.h>문제와 wchar_t to std::string 한글 문제
//4.12.5에서 사용한 코드
//FString path;//인자값
//std::string filename(TCHAR_TO_UTF8(*path));
//인코딩 문제 발생 : https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/StringHandling/CharacterEncoding/
const wchar_t* ptr = *path;
int csize = 1024; //글자 바이트 제한
char* tempFileName = new char[csize];
char def = '?';
//함수 참고 Url : https://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx
WideCharToMultiByte(CP_ACP, 0, ptr, -1, tempFileName, csize, &def, NULL);
std::string fileName(tempFileName);
delete[] tempFileName;
4.12.5 버전에서는 #include <Windows.h>를 하여
WideCharToMultiByte를 사용하였었다.
하지만 4.15.1로 오면서 #include <Windows.h> 를 사용하면
Winnt.h 에서 TEXT 매크로 재정의 Warning이 발생하는 등
여러 문제가 발생하여 #include <Windows.h>를 사용하지 않게 바꾸기로 했다.
wchar_t를 char*나 string으로 바꾸는 방법을 구글링으로 열심히 찾았으나
다 의미없는 소스와 블로그 글들 뿐이었다.
한글에 대한 처리가 고려되지 않는 글들도 많았다.
공식 MSDN이나 언리얼에서도 명확한 해결법을 주지 않았다.
UTF-16과 UTF-8에 대한 컨버팅 구조는 찾았으나
CP949로 가는 구조는 못찾았다.
2일째 고민하던 중 찾은 방법은 codecvt을 사용한 방법이었다.
저 헤더는 처음 봤다.(자세한 설명은 맨 위의 참고사이트 링크에 들어가보자.)
컨버트용 헤더로 생각된다.
//include해야 하는 헤더들
#include <string>
#include <vector>
#include <codecvt>
#include <locale>
//4.15.1에서 새로 작성한 코드
std::wstring str = *FilePath;
typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_t;
//std::locale loc = std::locale("ko_KR.UTF-8"); // windows 에서는 사용이 안됨
std::locale loc = std::locale("Korean"); // windows 용
codecvt_t const& codecvt = std::use_facet<codecvt_t>(loc);
std::mbstate_t state = std::mbstate_t();
std::vector<char> buf((str.size() + 1) * codecvt.max_length());
wchar_t const* in_next = str.c_str();
char* out_next = &buf[0];
std::codecvt_base::result r = codecvt.out(state,
str.c_str(), str.c_str() + str.size(), in_next,
&buf[0], &buf[0] + buf.size(), out_next);
if (r == std::codecvt_base::error)
throw std::runtime_error("can't convert wstring to string"); //실제 에러가 난다. 언리얼 로그로 바꾸어도 된다.
std::string fileName(&buf[0]);
위와 같이 바꾸니 Warning없이 정상적으로 동작한다.
복잡해보이니 아래와 같이 함수로 바꾸어 사용했다.(참고사이트에 있는 것 복붙 + 약간 수정)
std::string CommonFunc::WCStoMBCS(std::wstring const& str, std::locale const& loc /*= std::locale("")*/)
{
//loc에 std::locale("")로 들어오면 자동으로 OS의 locale을 찾는것 같다.(확인 필요), std::locale()로 하면 에러 난다.
typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_t;
codecvt_t const& codecvt = std::use_facet<codecvt_t>(loc);
std::mbstate_t state = std::mbstate_t();
std::vector<char> buf((str.size() + 1) * codecvt.max_length());
wchar_t const* in_next = str.c_str();
char* out_next = &buf[0];
std::codecvt_base::result r = codecvt.out(state,
str.c_str(), str.c_str() + str.size(), in_next,
&buf[0], &buf[0] + buf.size(), out_next);
if (r == std::codecvt_base::error)
throw std::runtime_error("can't convert wstring to string"); //실제 에러가 난다. UELOG로 바꾸어도 된다.
return std::string(&buf[0]);
}
마이그레이션 하던 것 중 제일 골치 아팠던 게 해결 되었다.
굿굿!!
'공부 > Unreal4' 카테고리의 다른 글
FindComponentByClass 의 위험성 (1) | 2017.04.14 |
---|---|
언리얼 c++에서 스폰된 액터 클래스 명으로 찾기 (0) | 2017.04.05 |
마이그레이션 중.. 싱글톤 설정 (0) | 2017.03.31 |
마이그레이션 중... 외부 라이브러리 사용 (0) | 2017.03.29 |
마이그레이션 중.. GrabComponent (0) | 2017.03.27 |