windows 如何最好地将 CString 转换为 BSTR 以将其作为“in”参数传递给 COM 方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2086493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:46:58  来源:igfitidea点击:

How to best convert CString to BSTR to pass it as an "in" parameter into a COM method?

windowsvisual-c++comatlbstr

提问by sharptooth

I need to convert a CStringinstance into a properly allocated BSTRand pass that BSTRinto a COM method. To have code that compiles and works indentically for both ANSI and Unicode I use CString::AllocSysString()to convert whatever format CStringto a Unicode BSTR.

我需要将CString实例转换为正确分配的实例并将其BSTR传递BSTR给 COM 方法。为了让代码同时为 ANSI 和 Unicode 编译和工作,我使用CString::AllocSysString()将任何格式转换CString为 Unicode BSTR。

Since noone owns the returned BSTR I need to take care of it and release it after the call is done in the most exception-safe manner posible and with as little code as possible.

由于没有人拥有返回的 BSTR,我需要处理它并在调用完成后以最异常安全的方式和尽可能少的代码释放它。

Currently I use ATL::CComBSTRfor lifetime management:

目前我ATL::CComBSTR用于终身管理:

 ATL::CComBSTR converted;
 converted.Attach( sourceString.AllocSysString() ); //simply attaches to BSTR, doesn't reallocate it
 interface->CallMethod( converted );

what I don't like here is that I need two separate statements to just construct the ATL::CComBSTRbound to the convertion result.

我不喜欢这里的是我需要两个单独的语句来构造ATL::CComBSTR转换结果的绑定。

Is there a better way to accomplish the same task?

有没有更好的方法来完成同样的任务?

回答by Phil Booth

CComBSTRhas overloaded constructors for both char*and wchar_t*, which make the call to SysAllocString()on your behalf. So the explicit allocation in your code snippet is actually unnecessary. The following would work just as well:

CComBSTR已重载两个构造char*wchar_t*,这使得调用SysAllocString()代表您。因此,您的代码片段中的显式分配实际上是不必要的。以下内容也同样有效:

ATL::CComBSTR converted = sourceString;
interface->CallMethod(converted);

Furthermore, if you have no need to use the converted BSTRelsewhere in your code, you can perform the object construction in-place in the method call, like so:

此外,如果您不需要BSTR在代码的其他地方使用转换后的对象,您可以在方法调用中就地执行对象构造,如下所示:

interface->CallMethod(ATL::CComBSTR(sourceString));

The same applies to the _bstr_tclass, which can be used instead of CComBSTRif you don't want a dependency on the ATL.

这同样适用于_bstr_t类,CComBSTR如果您不想依赖 ATL ,则可以使用它。

回答by Ramesh Alavala

One of the confusing aspects of Windows programming is managing the conversion of Visual Basic style strings to/from C language style strings. It isn't that it is so difficult, it is just difficult to remember the details. It is usually not done often, and the MSDN documentation is so voluminous that it is difficult to find answers to your questions. But, the worst part is that you could perform some typecast that compiles fine, but doesn't work the way you expect. This results in code that doesn't work, and the bugs are hard to track down. After some experience, you learn to make sure your string conversions are doing what you expect.

Windows 编程的一个令人困惑的方面是管理 Visual Basic 样式字符串与 C 语言样式字符串之间的转换。不是很难,只是细节很难记住。通常不会经常这样做,而且 MSDN 文档非常庞大,以至于很难找到问题的答案。但是,最糟糕的部分是您可以执行一些编译良好的类型转换,但不能按您期望的方式工作。这会导致代码不起作用,并且很难追踪错误。经过一些经验后,您将学会确保您的字符串转换符合您的预期。

C strings are arrays of characters terminated by a NULL character. Visual Basic strings differ in that the length of the string precede the characters in the string. So, a VB string knows its own length. In addition, all VB strings are Unicode (16 bits per character). String Types

C 字符串是由 NULL 字符终止的字符数组。Visual Basic 字符串的不同之处在于字符串的长度在字符串中的字符之前。因此,VB 字符串知道它自己的长度。此外,所有 VB 字符串都是 Unicode(每个字符 16 位)。字符串类型

BSTR/C String conversions are required if:

在以下情况下需要 BSTR/C 字符串转换:

You are doing COM programming in C/C++
You are writing multiple language applications, such as C++ DLL's accessed by Visual Basic applications.

回答by Afriza N. Arief

One of _bstr_tconstructors allows you to simply attach to existing BSTRso that you can have the exception that you want from CString::AllocSysStringwhen BSTRallocation fails.

其中一个_bstr_t构造函数,您只需连接到现有的BSTR,这样你可以有你想从异常CString::AllocSysStringBSTR分配失败。

// _bstr_t simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( _bstr_t(sourceString.AllocSysString(), false) );

The _bstr_tconstructor documentationsays:

_bstr_t构造的文件说:

_bstr_t(
   BSTR bstr,
   bool fCopy 
);

fCopy
If false, the bstrargument is attached to the new object without making a copy by calling SysAllocString.

fCopy
如果为 false,则bstr通过调用将参数附加到新对象而不进行复制SysAllocString

On the other hand, CComBSTRconstructordoesn't seem to have the corresponding signature; although it can be used as well if BSTRallocation failure exception is not really needed, as mentioned by Phil Boothin his answer.

另一方面,CComBSTR构造函数似乎没有相应的签名;尽管如果BSTR真的不需要分配失败异常,它也可以使用,正如Phil Booth他的回答中提到的。