c++ - 如何有效地将 BSTR 复制到 wchar_t[]?

标签 c++ com wchar-t bstr

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

最佳答案

首先,如果您需要做的只是阅读内容,您实际上可能根本不需要做任何事情。 BSTR 类型已经是指向空终止 wchar_t 数组的指针。事实上,如果您查看标题,您会发现 BSTR 本质上定义为:

typedef BSTR wchar_t*;

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

有两个重要的警告。

  1. BSTR 应该是不可变的。 BSTR 初始化后,您永远不应更改它的内容。如果您“更改它”,则必须创建一个新指针并分配新指针并释放旧指针(如果您拥有它)。
    [更新:这不是真的;对不起!您可以就地修改 BSTR;我很少有需要。]

  2. 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]'s Complete Guide To BSTR Semantics"

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

关于c++ - 如何有效地将 BSTR 复制到 wchar_t[]?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71980/

相关文章:

c++ - 为什么我可以传递这样的字符串参数?这种风格安全吗?

c++ - WAP八进制转二进制

java - 使用 C/C++ 或 Java 打开现金抽屉

c - 16 位 wchar_t 类型的最大码位是多少?

c++ - 比较 2 个 wchar_t 数组

c++ - Boost.Coroutine 在 iPhone 上崩溃

c++ - C++ 中的 median_unsafe 是什么意思

c++ - Com 线程/单元行为与编码工厂不一致

c++ - GetRecordInfoFromGuids() 因 TYPE_E_LIBNOTREGISTERED 而失败

c++ - 无法获取和显示用户名的C++ Microsoft示例