2008-09-16 16 views
5

私は、wchar__tオブジェクトにコピーするために変換したいBSTRオブジェクトを持っています。トリッキーなことは、BSTRオブジェクトの長さが数キロバイトから数百キロバイトになることです。データを効率的にコピーする方法はありますか?私はwchar_t配列を宣言するだけで、常に保持する必要のある最大限のデータを割り当てることができます。しかし、これは、何キロバイトしか必要としない何百万キロバイトのデータを割り当てることを意味する。助言がありますか?BSTRを効率的にwchar_t []にコピーしますか?

答えて

5

BSTRオブジェクトには長さ接頭辞が含まれているため、長さを見つけるのが安いです。長さを調べ、結果を保持するのに十分な大きさの新しい配列を割り当て、その中で処理し、完了したら解放することを忘れないでください。

0

ATLとCStringTを使用すると、代入演算子を使用できます。あるいは、USES_CONVERSIONマクロを使うことができます。これらはheap allocを使用しているため、メモリがリークしないことを保証します。

4

変換の必要はありません。 A BSTRポインタは文字列の最初の文字を指しており、NULLで終了します。長さはメモリの最初の文字の前に格納されます。 BSTRは常にUnicode(UTF-16/UCS-2)です。 ANSI BSTRと呼ばれるものがありました。これまでのAPIにはいくつかの参考文献がありますが、現在の開発ではこれらを無視することができます。

これは、wchar_tを期待する機能に安全にBSTRを渡すことができることを意味します。

BSTRunsigned shortへのポインタとして定義されているため、Visual Studio 2008ではコンパイラエラーが発生することがあります。wchar_tはネイティブタイプです。 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は、基本的にのように定義されていることがわかります。

重要な注意点が2つあります。

  1. BSTRは不変であるはずです。 BSTRが初期化された後は、BSTRの内容を決して変更しないでください。あなたが「変更する」場合は、新しいポインタを割り当てて新しいポインタを割り当て、古いポインタを解放する必要があります(所有している場合)。
    [UPDATE:これは正しくありません。ごめんなさい!その場でBSTRを変更することができます。私は非常に必要性はほとんどありません。]

  2. 従来のC/C++文字列は埋め込まれていないヌル文字を含むことができます。

あなたがBSTRのソースの制御のかなりの量を持っている、とBSTRは埋め込まれたヌルを持っていないことを保証することができる場合、あなたはそれが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:wcscpyに置き換えのstrcpy()()内例

+0

AFAIK、BSTRは*不変*ではないと思われます。だから彼らはconst *と宣言されていないのです。 – Constantin

+0

Hmmm ...私の立場を支持する参考文献は見つかりません。私が考えていたことは何でしょう?私はそれを訂正します。 –

+0

strcpyの代わりにwcscpyを使用してはいけませんか? – arolson101

関連する問題