我有一个BSTR对象,我想转换为复制到wchar__t对象.棘手的是BSTR对象的长度可能是几千字节到几百千字节.有没有一种有效的方法来复制数据?我知道我可以声明一个wchar_t数组,并总是分配它需要保存的最大可能数据.但是,这意味着为可能只需要几千字节的内容分配数百KB的数据.有什么建议?
首先,如果您需要做的只是阅读内容,您可能根本不需要做任何事情.BSTR类型是指向以null结尾的wchar_t数组的指针.实际上,如果检查标题,您会发现BSTR基本上定义为:
typedef BSTR wchar_t*;
因此,编译器无法区分它们,即使它们具有不同的语义.
有两个重要的警告.
BSTR应该是不可变的.在初始化之后,您永远不应该更改BSTR的内容.如果你"改变它",你必须创建一个新指针并分配旧指针(如果你拥有它).
[ 更新:这不是真的; 抱歉!您可以在适当的位置修改BSTR; 我很少有需要.]
允许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[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
如果您正在为BSTR使用类包装器,则包装器应该有一种方法可以为您调用SysStringLen().例如:
CComBString use .Length(); _bstr_t use .length();
更新:这是一篇关于这个主题的好文章,是一个比我更有知识的人:
"Eric [Lippert]完整的BSTR语义指南"
更新:在示例中将strcpy()替换为wcscpy()
BSTR对象包含长度前缀,因此找出长度很便宜.找出长度,分配一个足够大的新数组来保存结果,进行处理,并记住在完成后释放它.