如何有效地将 BSTR 复制到 wchar_t\[\]?

新手上路,请多包涵

我有一个 BSTR 对象,我想将其转换为复制到 wchar__t 对象。棘手的是 BSTR 对象的长度可能从几千字节到几百千字节不等。有没有一种有效的方法来复制数据?我知道我可以只声明一个 wchar_t 数组并始终分配它需要保存的最大可能数据。然而,这意味着为可能只需要几千字节的东西分配数百千字节的数据。有什么建议么?

原文由 Obediah Stane 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 448
1 个回答

首先,如果您需要做的只是阅读内容,您实际上可能根本不需要做任何事情。 BSTR 类型已经是指向以 null 结尾的 wchar_t 数组的指针。事实上,如果你查看 headers,你会发现 BSTR 本质上是这样定义的:

 typedef BSTR wchar_t*;

因此,即使它们具有不同的语义,编译器也无法区分它们。

有两个重要的警告。

  1. BSTR 应该是不可变的。在初始化 BSTR 后,您永远不应该更改它的内容。如果您“更改它”,则必须创建一个新指针并分配新指针并释放旧指针(如果您拥有它)。

[ 更新:这不是真的;对不起!您可以就地修改 BSTR;我很少有需要。]

  1. BSTR 允许包含嵌入的空字符,而传统的 C/C++ 字符串则不允许。

如果您对 BSTR 的来源有相当多的控制,并且可以保证 BSTR 没有嵌入的 NULL,则可以从 BSTR 中读取,就好像它是 wchar_t 一样,并使用传统的字符串方法(wcscpy 等)来访问它。如果没有,你的生活会变得更加艰难。您必须始终将数据作为更多 BSTR 或作为 wchar_t 的动态分配数组来操作。大多数与字符串相关的函数将无法正常工作。

假设您控制数据,或者不担心 NULL。我们还假设您确实需要制作副本并且不能直接读取现有的 BSTR。在这种情况下,您可以执行以下操作:

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

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

// ...

delete myString; // Done

如果您为 BSTR 使用类包装器,则包装器应该有一种方法可以为您调用 SysStringLen()。例如:

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

更新:这是一篇比我知识渊博的人写的关于这个主题的好文章:

“Eric [Lippert] 的 BSTR 语义完整指南”

更新:在示例中将 strcpy() 替换为 wcscpy()

原文由 Euro Micelli 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题