4

到目前为止,我发现我可以通过两种(许多?)方式将传入的 BSTR 转换为 ANSI,我很想知道在速度/效率等方面,一种是否比另一种“更好”。

我已经使用了一段时间的方式是使用USES_CONVERSIONandW2A宏,例如

BSTR __stdcall F(BSTR p1, BSTR p2 ) {
    USES_CONVERSION;

    LPSTR sNum1 = W2A( p1 );
    LPSTR sNum2 = W2A( p2 );

然而,最近,我遇到了另一种技术:

BSTR __stdcall F(BSTR p1, BSTR p2 ) {
    long amt = wcstombs( NULL, p1, 1 );
    sNum1 = (char *) malloc( amt ); 
    wcstombs( sNum1, p1, amt );
    *(sNum1 + amt) = '\0';

    amt = wcstombs( NULL, p2, 1 );
    sNum2 = (char *) malloc( amt ); 
    wcstombs( sNum2, p2, amt );
    *(sNum2 + amt) = '\0';

现在我承认,它更冗长,并且有两个调用,wcstombs但据我所知USES_CONVERSIONW2A宏可能隐藏着各种乐趣和游戏。

哪个代码更高效/更快?或者,我可以使用另一种技术来更好地完成这项工作吗?

4

4 回答 4

6

来自MSDN

[...]与 BSTR 字符串相互转换的推荐方法是使用CComBSTR类。要转换为 BSTR,请将现有字符串传递给 CComBSTR 的构造函数。要从 BSTR 转换,请使用 COLE2[C]DestinationType[EX],例如 COLE2T。

从 CComBSTR 页面:

[...]CComBSTR 类提供了许多将 ANSI 或 Unicode 字符串作为参数的成员(构造函数、赋值运算符和比较运算符)。这些函数的 ANSI 版本的效率低于 Unicode 版本,因为临时 Unicode 字符串通常是在内部创建的。为提高效率,请尽可能使用 Unicode 版本。

于 2009-02-23T05:48:43.437 回答
4

请注意尼克批准的答案,虽然正确,但与描述宏的 MSDN 文档存在相同的问题。

问题是某些宏,例如@Nick - COLE2A 列出的宏,实际上并不存在。

然而,在 MSDN 页面的下方,有一些文本可以提示您了解这一事实并让您能够找出正确的宏!

该文本列在下表中的以下文本下:

旧的字符串转换宏和新的字符串转换类之间有几个重要的区别:

在新 ATL 7.0 转换类列中。

其中说:

OLE 总是等价于 W

所以@Nick 示例中的宏实际上是CW2A

于 2010-03-04T12:43:31.257 回答
3

笔记:

如果您使用 ATL 宏,例如:COLE2[C]DestinationType[Ex](您可能应该这样做),请务必尽可能使用“C”版本,而不是您编写的非常量版本。它们可能等效于显式 BSTR->ASCII 转换(即:COLE2A),但对于不需要实际转换的转换(例如:为 UNICODE 编译时的 COLE2T),'C' 版本可以扩展为 noops,而非-'C' 如果源字符串是 const 版本仍将复制(因为您表示您需要生成的字符串是非常量的)。

另外值得注意的是:

新的 ATL7 宏并不总是需要USES_CONVERSION,但是它们分配临时的右值对象,而旧的宏使用_alloca。这可能很重要,也可能不重要,具体取决于您的使用情况(例如,不要在循环中使用旧的宏,它会运行很多次,这样做可能会破坏堆栈)。

于 2009-02-23T18:41:35.453 回答
1

自从我对 COM 或 BSTR 做任何事情以来已经有很长时间了,但我的建议是停止将 BSTR 视为特殊的东西。将它们视为指向宽字符零终止字符串的指针......如果这样做,将它们转换为 ANSI 可能会更容易。检查 Eric 的 BSTR 语义完整指南...

于 2009-02-24T05:33:49.567 回答