관리 메뉴

tapito.tistory.com

Win32 문자열 종류와 상호 변환 방법 #3 (완결) 본문

Application Programming Interface/Windows API

Win32 문자열 종류와 상호 변환 방법 #3 (완결)

Tapito 2018.03.06 21:49

Win32 C/C++ 문자열 종류와 상호 변환 방법 #3 (완결)

Win32 C/C++에는 문자열을 나타내는 자료형이 다양합니다. 그리고 그 자료형마다 용도와 역할이 있기 때문에 어느 하나만을 선택해서 사용할 수도 없습니다. 본 포스트에서는 이전 포스트에 이어서 Win32 C/C++에서 사용하는 문자열의 종류 중 COM, .NET에서 사용하는 문자열에 대해 설명하고 상호 변환 방법에 대해 설명하겠습니다.

 

1. BSTR, __bstr_t, CComBSTR

BSTRBasic String / Binary String은 COM에서 표준으로 사용하는 문자열입니다. 이 문자열은 마지막에 NULL 문자가 붙지 않는 대신 문자열의 맨 앞에 4바이트 정수로 크기를 명시하는 특징이 있습니다. 그렇기 때문에 Win32 C/C++에서 문자열 리터럴을 BSTR형 객체에 보관하기 위해서는 다음과 같이 SysAllocString으로 동적할당을 수행하며, 사용이 완료된 객체는 SysFreeString으로 해제합니다. 다음은 BSTR의 선언입니다.

typedef OLECHAR * BSTR;

 

여기서 혼동하지 말아야 할 것은, BSTR이 문자열 앞에 문자수를 동반하지만, BSTR이 가리키는 포인터는 문자열 그 자체라는 것입니다. 문자수를 얻고자 한다면 해당 포인터에서 4바이트 앞을 참조하면 되지만, 항상 4바이트일 것이라는 억측을 하면 안되므로 SysStringLen 함수로 하여금 문자 수를 대신 가져오게 합니다.

또한 문자열 앞에 문자열의 길이를 명시하므로 문자열의 끝에 반드시 NULL 문자가 붙을 필요는 없습니다. 다른 말로 문자열 끝에 NULL 문자가 있을것이라는 억측을 하면 안됩니다. 그러므로 BSTR을 C-Style로 변환하기 위해서 강제 형변환하는 것보다는, 별도로 제공된 함수를 사용하는 것이 안전합니다.

 

BSTR SysAllocString(
    OPT IN const OLECHAR * psz
);
void SysFreeString(
    BSTR bstrString
);
UINT SysStringLen(
    OPT IN BSTR bstr
);

 

이 함수를 사용하여 OLECHAR 문자열을 BSTR로 변환하고, 사용이 끝난 문자열을 해제해 보겠습니다.

/* Example */
OLECHAR ocs[] = OLESTR("테스트 문자열.");
BSTR bstr;

/* ... */

bstr = SysAllocString(ocs);

// ... BSTR로 처리될 작업

SysFreeString(bstr);

/* ... */

 

BSTR에서 OLECHAR 문자열로 변환하기 위해, 앞서 설명된 매크로 함수를 사용할 수 있습니다.

/* Example */
#include <atlconv.h>

BSTR bstr;
LPTSTR tcs = NULL;

/* ... */

USES_CONVERSION;
tcs = OLE2T(bstr);

/* ... */

 

1-2. __bstr_t, CComBSTR

__bstr_t와 CComBSTR은 공통적으로 BSTR 형 문자열과 관련 함수들을 하나의 클래스로 캡슐화 한 것입니다. 다만, __bstr_t는 Compiler COM Support에서 사용하는 자료형으로서 comutil.h 헤더파일에 정의되어 있고, CComBSTR은 ATL에서 사용하는 자료형으로서 atlbase.h에 정의되어 있다는 차이가 있습니다. 여기서 Compiler COM Support는 COM을 지원하는 라이브러리 파일을 소스 코드에서 #import 구문으로 포함시켰을 때 컴파일러가 자동으로 내부 클래스와 메서드를 선언하는 구문을 생성하는 것을 뜻합니다.

 

2. System::String ^

System::String ^은 .NET Framework에서 지원하는 System.String 형을 C++/CLI서 부르는 명칭입니다. 다음과 같이 생성자로 Multibyte String과 Wide String의 두 가지를 받을 수 있고, 메모리 고정을 통해 Wide String으로 변환할 수 있습니다.

/* Example */
TCHAR tcs1[] = TEXT("안녕하세요.");
TCHAR tcs2[56] = { TEXT('\0'), };

System::String ^ gcs = nullptr;
pin_ptr pcs = nullptr;

gcs = gcnew System::String(tcs1); // C-Style에서 관리되는 문자열로 변환
pcs = PtrToStringChars(gcs); // 관리되는 문자열에서 C-Style 버퍼 얻기

// wchar_t *가 필요한 곳에 pcs를 대입 가능

 

추가적으로 관리되는 배열을 C-Style 배열로 변환하는 소스 패턴은 다음과 같습니다.

/* Example */
cli::array^ origin = gcnew cli::array(/* ... */);
cli::pin_ptr conv = &origin[0];

// ... conv를 포인터 배열처럼 사용

 

참고 자료

pin_ptr (C++/CLI) - MSDN
https://msdn.microsoft.com/ko-kr/library/1dz8byfh.aspx
How to convert from System::String* to Char* in Visual C++ - MSDN
https://support.microsoft.com/en-us/help/311259/how-to-convert-from-system-string-to-char-in-visual-c
Working with strings in COM, MFC, Win32, STL / Unraveling Strings in Visual C++
https://www.johndcook.com/blog/cplusplus_strings/

 

 

0 Comments
댓글쓰기 폼