midas+son의 크리에이티브(creative) 이야기

//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]);

}

마이그레이션 하던 것 중 제일 골치 아팠던 게 해결 되었다.

굿굿!!