翻译《有关编程、重构及其他的终极问题?》——27.狡猾的BSTR字符串

本文深入探讨了COM中使用的BSTR字符串类型,揭示了其与wchar_t*的区别,并提供了正确使用BSTR的指导。

翻译《有关编程、重构及其他的终极问题?》——27.狡猾的BSTR字符串

标签(空格分隔): 翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2017年06月20日


27.狡猾的BSSTR字符串

让我们再讨论一个讨厌的数据类型——BSTR(basic string或者binary string)。

下面这段代码来自VirtualBox项目。这段代码包含被PVS-Studio分析诊断的错误: V745 A ‘wchar_t ’ type string is incorrectly converted to ‘BSTR’ type string. Consider using ‘SysAllocString’ function(译者注:大意是“wchar_t “不能正确的转换为“BSTR”类型,请考虑适用“SysAllocString”函数)。

....
HRESULT EventClassID(BSTR bstrEventClassID);
....
hr = pIEventSubscription->put_EventClassID(
                    L"{d5978630-5b9f-11d1-8dd2-00aa004abd5e}");

解释
下面是BSTR类型被定义的方式:

typedef wchar_t OLECHAR;
typedef OLECHAR * BSTR;

第一眼看去,好像“wchar_t *”和BSTR是一模一样的,但其实并非如此,这也导致了很多困惑和错误。

让我们用一种更好的方式来讨论有关BSTR的问题吧。

下面这些信息来自MSDN的官网。虽然读MSDN文档不是太开心的事情,但我们不得不读。

BSTR(基本的字符串或二进制字符串)是一种被COM(译者注:是一种微软历史上大力提倡的组件技术,2000左右就慢慢没落了,现在Windows上还在使用,但不需要用户关注太多了)、自动化和交互操作等函数使用的字符串数据类型。在所有使用BSTR数据类型使用的接口可以被脚本语言调用。下面是BSTR的描述:
1. 前置长度:最前面有4个字节的整型,其中包含了后续紧跟着的整个字符串的字节长度值。这个值不包括字符串结尾符;
2. **字符串数据:**Unicode编码的字符串,还可能包含多个嵌入的null字符。
3. 结尾符:两个null字符。
BSTR是一个指针,其指向字符串数据的第一个字符,而不是指向前置长度。BSTR使用COM内存分配函数分配内存,所以它们由方法返回而无须关心内存分配。下面的代码市错误的:

BSTR MyBstr = L"I am a happy BSTR";

这个代码可以通过编译,但因为没有包含前置长度所以MyBstr不能正常的工作。如果你用调试器区检查这个变量对应位置的内存,你不会看到4个字节用于处理字符串数据的前置长度。相反,请使用如下代码:

BSTR MyBstr = SysAllocString(L"I am a happy BSTR");

现在,检查这个变量对应位置内存的调试器将会看到一个值为34的前置长度。对于一个长度为17的单字节字符串而言,通过“L”字符操作符将其转换为宽字节,34就是其对应的长度。调试器还能在字符串的结尾看到一个两字节的字符串结尾符号(0x0000)。

在原本期望BSTR的COM函数中,如果你只是简单的传入Unicode字符串作为变量,这个COM函数会失败。

我希望这对你来说已经足够了解为何我们应该区分对待BAST和“wchar_t *”字符串类型。

下面是额外的一些参考链接:
1. MSDN:BSTR
2. StackOverflow:针对给BSTR传入“wchar_t *”的静态代码分析
3. StackOverflow:从BSTR到std::string(std::wstring)以及相反的过程
4. Robert Pittenger:BSTR和CString转换的向导
5. Eric Lippert:Eric针对BSTR语法的完整向导

正确的代码

hr = pIEventSubscription->put_EventClassID(
       SysAllocString(L"{d5978630-5b9f-11d1-8dd2-00aa004abd5e}"));

建议
这次说的和上一个章说的类似,如果你看到一个未知的类型,最好不要慌张,并且耐心的去查看相关文档,这非常重要,所以这一章有些啰嗦也情有可原。

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值