윈도우의 System API들은 ANSI 문자열이나 유니코드 문자열을 받도록 되어 있다.
하지만 아스키코드와 유니코드를 처리하기 위해 시스템에서 char, wchar_t, string, wstring등을 혼용하면서 사용하는것은 불편하다고 생각된다.(ex: 문자열을 json으로 저장할때 아스키와 유니코드 처리등...)
그래서 가급적이면 시스템에서는 하나의 문자열을 사용하는 것이 좋을 것 같다.
한글이나 일본어 같은 유니코드 문자들을 ansi로 변경한 후 WindowsApiA 같이 끝이 A로 끝나는 API들만 호출 하도록 처리 하는 것이다.
이 방법은 유니코드가 시스템에 들어오는 지점에서 ANSI로 문자열을 변경하는 처리만 잘 해주면 시스템 안에서 문자열들은 string 하나의 타입만으로도 가능 하다.
#include <windows.h>
inline DWORD convert_unicode_to_ansi_string(
__out std::string& ansi,
__in const wchar_t* unicode,
__in const size_t unicode_size) {
DWORD error = 0; do {
if ((nullptr == unicode) || (0 == unicode_size)) {
error = ERROR_INVALID_PARAMETER;
break;
}
ansi.clear();
/*
* getting required cch.
*/
int required_cch = ::WideCharToMultiByte(
CP_ACP, 0, unicode, static_cast<int>(unicode_size), nullptr, 0, nullptr, nullptr);
if (0 == required_cch) {
error = ::GetLastError();
break;
}
/*
* allocate.
*/
ansi.resize(required_cch);
/*
* convert.
*/
if (0 == ::WideCharToMultiByte(
CP_ACP, 0, unicode, static_cast<int>(unicode_size), const_cast<char*>(ansi.c_str()),
static_cast<int>(ansi.size()), nullptr, nullptr)) {
error = ::GetLastError();
break;
}
} while (false);
return error;
}
inline std::string convert_utf16_to_ansi(const wchar_t* str) {
std::wstring intput_str(str);
std::string output_str;
convert_unicode_to_ansi_string(output_str, intput_str.c_str(), intput_str.size());
return output_str;
}
std::string ansi_to_utf8(const std::string& str) {
const char* pszIn = str.c_str();
std::string resultString;
int nLenOfUni = 0, nLenOfUTF = 0;
wchar_t* us = NULL;
char* pszOut = NULL;
if ((nLenOfUni = MultiByteToWideChar(CP_ACP, 0, pszIn, strlen(pszIn), NULL, 0)) <= 0) {
return str;
}
us = new wchar_t[nLenOfUni + 1];
memset(us, 0x00, sizeof(wchar_t) * (nLenOfUni + 1));
// ansi -> unicode
nLenOfUni = MultiByteToWideChar(CP_ACP, 0, pszIn, strlen(pszIn), us, nLenOfUni);
if ((nLenOfUTF = WideCharToMultiByte(CP_UTF8, 0, us, nLenOfUni, NULL, 0, NULL, NULL)) <= 0) {
delete[] us;
return str;
}
pszOut = new char[nLenOfUTF + 1];
memset(pszOut, 0x00, sizeof(char) * (nLenOfUTF + 1));
// unicode -> utf8
nLenOfUTF = WideCharToMultiByte(CP_UTF8, 0, us, nLenOfUni, pszOut, nLenOfUTF, NULL, NULL);
pszOut[nLenOfUTF] = 0;
resultString = pszOut;
delete[] us;
delete[] pszOut;
return resultString;
}
//example
__declspec(dllexport) void __stdcall Example(
const char16_t* file_path) {
auto ansi_file_path = convert_utf16_to_ansi((const wchar_t*)file_path);
PathFindFileNameA(ansi_file_path.c_str())
DWORD h = 0;
DWORD resource_size = ::GetFileVersionInfoSizeA(const_cast<char*>(ansi_file_path.c_str()), &h);
}