^(코딩캣)^ = @"코딩"하는 고양이;

[Win32 문자열 종류와 상호 변환 방법] Part 3 - COM/.NET 문자열 (完)

Microsoft Windows/Win32 문자열 처리
2019. 3. 11. 11:13

Win32 C/C++ 문자열 종류와 상호 변환 방법


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/

 

 

카테고리 “Microsoft Windows/Win32 문자열 처리”
more...