2008-09-16 5 views
5

wchar__t 개체로 복사하도록 변환하려는 BSTR 개체가 있습니다. 까다로운 것은 BSTR 객체의 길이가 수 킬로바이트에서 수 백 킬로바이트가 될 수 있다는 것입니다. 데이터를 효율적으로 복사하는 방법이 있습니까? 나는 wchar_t 배열을 선언 할 수 있고, 항상 보유 할 최대 가능한 데이터를 할당 할 수 있음을 알고있다. 그러나 이것은 잠재적으로 수 킬로바이트 만 필요할 수도있는 수백 킬로바이트의 데이터를 할당하는 것을 의미합니다. 어떤 제안?효율적으로 BSTR을 wchar_t []에 복사합니까?

답변

5

BSTR 개체에는 길이 접두사가 있으므로 길이를 찾는 것이 저렴합니다. 길이를 알아 내고, 결과를 저장할 수있을만큼 큰 새로운 배열을 할당하고, 처리하고, 끝나면 그것을 자유롭게한다는 것을 기억하십시오.

0

ATL 및 CStringT를 사용하면 할당 연산자 만 사용할 수 있습니다. 또는 USES_CONVERSION 매크로를 사용할 수 있습니다.이 매크로는 heap alloc을 사용하므로 메모리가 누출되지는 않습니다.

4

변환 할 필요가 없습니다. BSTR 포인터는 문자열의 첫 번째 문자를 가리키며 null로 끝납니다. 길이는 메모리의 첫 번째 문자 앞에 저장됩니다. BSTR은 항상 유니 코드 (UTF-16/UCS-2)입니다. 한 단계에서 'ANSI BSTR'이라고하는 항목이있었습니다. 기존 API에는 몇 가지 참조가 있지만 현재 개발 중에는이를 무시할 수 있습니다.

즉, BSTRwchar_t을 예상하는 모든 기능에 안전하게 전달할 수 있습니다.

BSTRunsigned short에 대한 포인터로 정의되어 있고 wchar_t이 기본 형식이기 때문에 Visual Studio 2008에서 컴파일러 오류가 발생할 수 있습니다. wchar_t을 전송하거나 /Zc:wchar_t 준수를 해제 할 수 있습니다.

+1

wchar_t는 short의 크기와 정확히 일치하지 않을 수 있습니다. – ben

+0

이 작업은 항상 안전하다고 생각하지만 항상 예상되는 결과를 제공하지는 않습니다. BSTR은 본문에 널 문자 (따라서 길이 접두어)를 포함 할 수 있지만 wchar_t *를 예상하는 함수는 첫 번째 널 문자를 문자열의 끝으로 해석합니다. – Martin

+8

"wchar_t *를 기대하는 함수에는 BSTR을 안전하게 전달할 수 없습니다." SysStringLen (NULL)과 wcslen (NULL)을 비교하십시오. – Constantin

3

염두에 두어야 할 점 중 하나는 BSTR 문자열에 포함 된 null이 포함될 수 있으며 종종 수행해야한다는 것입니다. null는 문자열의 끝을 의미하지 않습니다.

7

먼저, 실제로 내용을 읽을 필요가 전혀없는 경우가 있습니다. BSTR 유형은 널 (null)로 끝나는 wchar_t 배열에 대한 포인터입니다.

typedef BSTR wchar_t*; 

그래서 컴파일러는 서로 다른 의미를 가지고에도 불구하고, 그들 사이에 구별 할 수 없습니다 : 당신이 헤더를 확인하면 사실, 당신은 BSTR 본질적으로 정의되어 있습니다.

두 가지 중요한주의 사항이 있습니다.

  1. 하고 BSTR은 변경할 수 있어야한다. BSTR을 초기화 한 후에는 내용을 절대 변경해서는 안됩니다. "변경"하면 새 포인터를 할당하고 새 포인터를 할당하고 이전 포인터를 소유해야합니다 (소유하고있는 경우).
    [업데이트 : 이것은 사실이 아닙니다. 죄송합니다! BSTR을 제자리에서 수정할 수 있습니다. 나는 거의 필요가 거의 없었습니다.]

  2. 전통적인 C/C++ 문자열은 그렇지 않지만 BSTR에는 내장 된 null 문자가 포함될 수 있습니다.

당신이 BSTR의 소스 컨트롤의 공정한 금액을 가지고 있고, BSTR이 포함 된 널 (NULL)이 없음을 보장 할 수 있다면, 당신은 그것이 wchar_t를했다 것처럼 BSTR에서 읽고 기존의 문자열을 사용할 수 있습니다 메소드 (wcscpy 등)를 사용하여 액세스하십시오. 그렇지 않다면 당신의 삶은 점점 더 어려워집니다. 더 많은 BSTR 또는 항상 동적으로 할당 된 wchar_t 배열로 데이터를 조작해야합니다. 대부분의 문자열 관련 함수는 올바르게 작동하지 않습니다.

데이터를 제어한다고 가정하거나 NULL에 대해 걱정하지 마십시오. 또한 사본을 만들 필요가 있고 기존 BSTR을 직접 읽을 수는 없다고 가정 해 보겠습니다. 이 경우,이 같은 것을 할 수 있습니다 : 당신이 당신의 BSTR에 대한 클래스 래퍼를 사용하는 경우

UINT length = SysStringLen(myBstr);  // Ask COM for the size of the BSTR 
wchar_t *myString = new wchar_t[lenght+1]; // Note: SysStringLen doesn't 
              // include the space needed for the NULL 

wcscpy(myString, myBstr);     // Or your favorite safer string function 

// ... 

delete myString; // Done 

을 래퍼가 당신을 위해() SysStringLen를 호출 할 수있는 방법이 있어야합니다.

CComBString use .Length(); 
_bstr_t  use .length(); 

UPDATE : 예를 들어
"Eric [Lippert]'s Complete Guide To BSTR Semantics"

UPDATE : 대체의 strcpy() wcscpy와()에서이 나보다 훨씬 더 많은 지식이있는 사람에 의해 주제에 대한 좋은 기사입니다 예 :

+0

AFAIK, BSTR은 변경할 수 없습니다. 그것이 const *로 선언되지 않은 이유입니다. – Constantin

+0

음 ... 내 위치를 뒷받침하는 참조를 찾을 수 없습니다. 내가 뭘 생각 했어? 나는 그것을 바로 잡을 것이다. –

+0

strcpy 대신 wcscpy를 사용하면 안됩니까? – arolson101