Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr

레거시 C++앱을 유니코드로 마이그레이션 하는 방법


Recommended Posts

(역자 주: 잘못되거나 부족한 번역이 있으면 알려주세요. 언제나 환영합니다)

This brief article focuses on helping you migrate your legacy C++ Builder applications to Unicode. Based on information from the Embarcadero consultants here you will find tips, tricks, and techniques to migrate legacy C++ Builder apps to a newer version.

이 짧은 기고에서는 C++빌더 레거시 애플리케이션을 유니코드로 마이그레이션하는데 도움을 주는 것에 집중한다. 엠바카데로 컨설턴트가 제공하는 정보를 기반으로, 레거시 C++빌더 앱을 새로운 버전으로 마이그레이션할 때의 팁, 요령, 기술 내용을 다룬다.

 

We will look at working with Unicode in C++ Builder. For example you may know for the string datatype C++ Builder offers several choices. Your code can utilize C-style characters and strings or C++ string objects for VCL string objects and each of these has its own set of Unicode variations. Moreover, the Windows API provides both ANSI and Unicode variants of various functions and methods.

우선 C++빌더에서 유니코드로 작업하는 방법을 살펴보겠다. 예를 들어, C++빌더가 다양한 문자열 데이터 타입을 제공하는 것을 알고 있을 것이다. 코드에서 C스타일로된 문자와 문자열을 활용하거나 VCL 문자열 오브젝트 용 C++ 문자열 오브젝트를 활용할 수 있으며, 이들 각자는 고유한 유니코드로 변형된 세트를 가지고 있다. 게다가, 윈도우 API에서 제공하는 다양한 함수와 메소드는 ANSI와 유니코드 버전을 둘다 제공한다.

 

  • New C and C++ data types for C-style strings
  • New Unicode VCL string classes
     
  • C와 C++의 새 데이터 타입(들): C-스타일 문자열용 
  • 새 유니코드 VCL 문자열 클래스(들) 

 

We will look at how to use the _TCHAR maps to option that determines whether or not the Unicode preprocessor macro is defined. Then that determines whether you get the ANSI variant or the Wide string UTF-16 variant.

우리는 유니코드 전처리 매크로 정의 여부를 결정하는 옵션에 _TCHAR 맵을 사용하는 방법에 대해 살펴볼 것이다. 이 작업을 하고 나면, 문자열이 ANSI Variant와 Wide string UTF-16 Varient 중 어느 것으로 적용될지가 결정된다.

 

Furthermore, we will look at the standard Windows header tchar that includes macros designed to let you write code that compiles as either ANSI or Unicode.

더 나아가, 우리는 준 윈도우 헤더 tchar를 알아볼 것이다. 이 헤더에는 ANSI와 유니코드 중 하나로 컴파일하는 코드를 작성할 수 있도록 하는 매크로가 들어있다.

 

Then finally, we will give examples for loading and saving Unicode characters to file.

마지막으로, 유니코드 문자 파일을 로드하고 저장하는 예제를 제공한다. 

 

C++빌더에서 유니코드에 대해 알고 있어야 하는 점 

Unicode in C++ Builder 2009 has full Unicode support throughout both the VCL and the runtime library. The Unicode is critical for internationalization and localization. 

C++빌더 2009에 있는 유니코드는 VCL과 런타임 라이브러리 전체에서 유니코드를 완전하게 지원한다. 유니코드는 현지화, 국제화에 있어 매우 중요하다. 

 

C++ is a diverse language permitting the use of many libraries and several programming paradigms and, while your code uses the VCL does not need to be Unicode-aware. So, this means you might not need to convert all your code to a newer version. You can use your C runtime library, STL, or the Windows API, but when you need to pass data to or from VCL you can convert to Unicode.

C++은 수많은 라이브러리와 여러 프로그래밍 패러다임을 사용할 수 있도록 허용하는 언어다. 그렇긴 하지만, VCL을 사용하는 코드는 굳이 유니코드를 인식하지 못해도 괜찮다. 그 의미는 당신의 코드를 모두 최신 버전으로 변환할 필요가 없을 수도 있다는 뜻이다. C 런타임 라이브러리, STL, 윈도우 API를 사용하는 코드는 그대로 사용해도 괜찮다. 하지만 VCL을 대상으로 데이터를 전달하거나 받아오는 코드에서는 유니코드 변환이 필요할  수 있다.

 

어떤 경우에 유니코드로 완전히 마이그레이션해야 하는가? 

By completely migrating to Unicode you can gain the full benefits of internationalization but, migrating only the VCL portion of your code can also simplify the task of upgrading. 

국제화의 장점을 모두 취하려면 유니코드로 완전히 마이그레이션 하는 것이 좋다. 하지만 그렇지 않다면, 코드에서 해당되는 VCL 부분만 마이그레이션 함으로써 업그레이드 작업을 간소화 할 수 있다. 

 

To completely convert to Unicode, we need to explore several techniques.

완전하게 유니코드로 변환하기 위해서는, 몇 가지 기술을 살펴봐야 한다. 

 

C++빌더 프로젝트를 이전 버전에서 업데이트하는 방법

There are 2 options to start:

시작할 때는 다음 두 가지 방법 중 하나를 선택할 수 있다: 

  1. C++빌더에서 당신의 프로젝트 파일을 연다. 
    • IDE가 당신의 프로젝트 파일을 알아서 업데이트한다. 
    • 다시 빌드한다.
    • 오류와 경고를 확인하고 고친다. 
  2. C++빌더가 알아서 새 버전으로 변환하지 않도록 하기
    • 새로운 폴더에 당신의 파일(들)을 복사한다.
    • 빈 프로젝트를 새로 하나 생성한다. 
    • 생성된 프로젝트 안에 소스 파일(들)을 추가한다. 

The second option is much more efficient but takes time.

두 번째 옵션이 훨씬 더 효율적이지만 파일(들)을 추가하는 데 시간이 걸린다. 

 

VCL의 유니코드에 대해 알고 있어야 하는 점 

Unicode in VCL we see that the VCL offers these 6 string classes which support ANSI UTF-8 and UTF16 encoding.

VCL에서 유니코드는 다음과 같은 6개의 문자열 클래스를 제공하는데, 이들은 VCL에서 ANSI UTF-8과 UTF16 인코딩을 지원한다. 

 

Note: code page is a character set, which can include numbers, punctuation marks, and other glyphs.

참고: 코드 페이지는 일종의 문자 집합인데, 여기에는 숫자, 문장부호, 기타 상형문자(glyph)가 들어있다. 

  • AnsiString - 시스템 안에 있는 8비트 문자 데이터가 들어있는 예전의 문자열 클래스와 대응된다. 
  • UnicodeString - 새로운 클래스이다. UTF-16으로 인코딩된 16비트 크기의 char_t 데이터가 포함되어 있다. 
  • WideString – 이전 버전의 RAD스튜디오에 있는 클래스로 COM, Automation, Interop 기능에서 사용되는 BSTR (기본 문자열 또는 이진 문자열) 데이터 타입에 대응된다. 유니코드 문자열과 마찬가지로 16비트 크기의 char-t 데이터가 포함되어 있다. 
  • AnsiStringT - 코드 페이지에 인코딩된 8비트 문자 데이터가 포함된 클래스 템플릿이다. 
  • UTF8String – UTF-8 인코딩을 사용하는 AnsiStringT 인스턴스화이다. 
  • RawByteString - 지정되지 않은 코드 페이지에 8-bit char 데이터가 포함되어 있다. 

Using RawByteString can give several advantages since each code page is a separate, compile-time type. RawByteString lets you write a single routine that can handle any code page. It removes any VCL overhead of doing code page conversions itself, and it prevents possible loss of data from automatically converting text data into encodings that can’t represent some characters.

RawByteString를 사용하면, 각 코드 페이지가 컴파일 시 정해져 여러 이점을 제공한다. RawByteString으로 모든 코드 페이지를 처리할 수 있는 단일 루틴을 작성할 수 있다. 코드 페이지를 변환하는 VCL 오버헤드를 제거하고, 텍스트 데이터는 일부 문자를 표시할 수 없는 인코딩으로 자동 변환함으로써 발생할 수 있는 데이터 손실 가능성을 방지한다. 

 

The good news with all of this is that most member functions of these new string classes operate just the same as they did for the old non-Unicode string classes.

좋은 소식은, 새로운 문자열 클래스 멤버 함수 대부분이 이전의 비 유니코드 문자열 클래스와 동일하게 작동한다는 것이다. 

 

AnsiStringT<CodePage> 템플릿 예제: 

  • We pass Cyrillic data from CodePage 1251 to 65001 and back to Unicode without data loss

  • (러시아와 동유럽 등지에서 사용되는) 키릴 문자를 담은 데이터를 다루려면, CodePage 1251에서 CodePage  65001로  변환하고, 이것을 다시 유니 코드 문자열로 변환하면 데이터가 손실되지 않고 잘 변환된다. 
const wchar_t* data = L"Что ты говоришь?"; 
{ 
  // (러시아, 동유럽 등의) 키릴 문자를 담은 데이터를 다룰 때,
  // CP 1251 -> CP_UTF8 -> UnicodeString으로 손실 없이 변환하는 예시 
  AnsiStringT<1251> cp1251Str = data; 
  assert(cp1251Str.CodePage() == 1251); 

  UTF8String utf8Str = cp1251Str; 
  assert(utf8Str.CodePage() == CP_UTF8); 

  UnicodeString us1 = cp1251Str; 
  UnicodeString us2(utf8Str); 

  assert(us1 == us2); 
  assert(us1 == data); 
  assert(us2 == data); 
} 

 

유니코드와 윈도우 API에 대해 알아야 할 점

Windows API includes both Unicode and ANSI variants.

윈도우 API에는 유니코드와 ANSI 버전이 모두 포함되어 있다. 

  • MessageBoxA – ANSI 문자열 사용 
  • MessageBoxW - wide (UTF-16) 문자열 사용 
#if defined(UNICODE) 
  ::MessageBox(Handle, Edit1->Text.c_str(), // wchar_t* 
          _T("MessageBox - text from Edit1->Text.c_str()"), MB_OK); 
#else 
  ::MessageBox(Handle, AnsiString(Edit1->Text).c_str(), 
          AnsiString("MessageBox").c_str(), MB_OK); 
#endif 

 

 

C스타일 문자열에 어떤 새로운 C와 C++ 데이터 유형이 있을까? 

  • char16_t (예: u”Hello, World! u263A”) - > UTF-16 
    • wchar_t와 동일한 의미 
  • char32_t (예: U”Hello World! u263A”) - >UTF-32 
  • C++에는 고유한 AnsiString 타입을 만들 수 있는 AnsiStringT 코드페이지 템플릿이 있다. 

 

왜 TCHAR.H를 써야할까? 

If you are planning on a complete Unicode migration as part of an upgrade to C++ Builder’s latest versions, character width agnostic code lets you prepare for the migration in your previous version of C++ Builder without breaking compilation. 

C++빌더 최신 버전으로 업그레이드할 때 완벽한 유니코드 마이그레이션을 계획하고 있다면, 문자 너비 제한 코드를 사용해 컴파일을 중단하지 않고도 C++빌더 이전 버전에서 마이그레이션을 준비할 수 있다. 

 

Windows provides us with this TCHAR header file to help with this. Depending on whether the underscore Unicode preprocessor macro is defined, this TCHAR header defines the following macros for Unicode builds.

윈도우는 이를 지원하기 위해 TCHAR 헤더 파일을 제공한다. 언더바(underscore) 유니코드 전처리기 매크로 정의 여부에 따라, TCHAR 헤더는 유니코드 빌드에 다음의 매크로를 정의한다. 

 

  • TCHAR defined as
    • char for non-Unicode builds
    • wchar_t for Unicode builds
  • _T, which is removed by the preprocessor for non-Unicode builds and is defined as L for Unicode builds
    • _T(“Hello, world”) and the preprocessor converts it to a char literal
    • wchar_t literal (L”Hello, world”) as appropriate
       
  • TCHAR는 다음과 같이 정의된다. 
    • 비 유니코드 빌드용 char 
    • 유니코드 빌드용 wchar_t 
  • _T는 비 유니코드 빌드의 경우 전처리에 의해 제거되며, 유니코드 빌드의 경우 L로 정의된다. 
    • _T(“Hello, world”)와 전처리는 이를 char 리터럴로 변환한다. 
    • wchar_t 리터럴 (L”Hello, world”)이 적합하다. 

 

문자열의 일부를 AnsiString으로 바꾸는 방법

Here is one of the tips that talks about should you just go ahead and replace all occurrences of a string with an AnsiString. It is better to not just replace all occurrences of a string with AnsiString but instead use these two functions. You can use them whenever one type is returned and, the other type is required and vice-versa. 

문자열의 모든 문자를 AnsiString으로 변환해야 하는 지에 대한 팁을 주자면, 문자열의 모든 문자를 AnsiString으로 변환하는 것보다는 이 함수 두개를 사용하자. 반환된 타입이 아닌 다른 타입이 필요한 때 사용할 수 있고, 각 함수는 서로 반대되는 타입으로 변환한다. 

wchar_t* __fastcall UnicodeOf(const char* C) 
{ 
  static wchar_t W[STR_CONV_BUF_SIZE]; 
  memset(w, 0, sizeof(W)); 
  MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, c, strlen(c), W, STR_CONV_BUF_SIZE); 
  return(W); 
} 

char* __fastcall AnsiOf(wchar_t* W) 
{ 
  static char c[STR_CONV_BUF_SIZE]; 
  memset(c, 0, sizeof(c)); 
  WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, w, wcslen(w), c, STR_CONV_BUF_SIZE, NULL, NULL); 
  return(c); 
} 

With these two functions, we’re using the two Windows API functions once called the wide char into multibyte that converts from UTF-16 to the encoding of your choices. For instance, UTF-8 or any of the various ANSI encodings.

이 두 함수를 통해, 한 때 wide char라고 불렸던 두 개의 윈도우 API 함수를 UTF-16에서 선택한 인코딩으로 변환하는 멀티바이트로 사용하게 된다. 예를 들어, UTF-8 또는 다양한 ANSI 인코딩이 있다. 

 

유니코드 문자를 파일에 로드 및 저장하는 방법은? 

LoadFromFile and SaveToFile methods now have an additional parameter which is the TEncoding class. TEncoding class has a static property where you can, specify the encoding either ASCII or UTF-8 or Unicode or others.

LoadFromFile와 SaveToFile 메소드에는 TEncoding 클래스라는 추가 파라메터가 포함되어있다. TEncoding 클래스에는 정적 프로퍼티가 있는데, ASCII 나 UTF-8, 유니코드 등 중 하나를 인코딩 지정할 수 있는 프로퍼티이다.  

ListBox1->Items->SaveToFile("c:tempmyText.txt", TEncoding::UTF8); 

if (FileExists("c:tempmyText.txt")) { 
  ListBox1->Items->LoadFromFile("c:tempmyText.txt", TEncoding::UTF8); 
} else { 
  ShowMessage("c:tempmyText.txt does not exist!"); 
}

 

유니코드를 적용하는 C++앱 마이그레이션 방법을 설명하는 영상 

오래된 레거시 C++빌더 프로젝트를 새 버전으로 마이그레이션 하는 방법에 대해서 더 배우고 싶으면, 이 웨비나 비디오를 보기 바란다.

 

C++앱을 유니코드로 마이그레이션 하는 방법에 대한 더 많은 내용은 어디에서 찾을 수 있을까? 

이번 글에서는 유니코드 변환과 관련하여 피상적인 내용을 매우 간략하게 다루었다. 유니코드 마이그레이션 등 더 많은 마이그레이션 정보는 데브기어 마이그레이션 업그레이드 센터를 통해 확인할 수 있으며, 무상 컨설팅도 받을 수 있다. 

 

 

이 댓글 링크
다른 사이트에 공유하기

이 토의에 참여하세요

지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.

Guest
이 토픽(기고/질문)에 답하기

×   서식있는 텍스트로 붙여넣기.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   이전에 작성한 콘텐츠가 복원되었습니다..   편집창 비우기

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.