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

发布于 2024-08-18 14:29:08 字数 581 浏览 6 评论 0原文

我需要将 CString 实例转换为正确分配的 BSTR 并将该 BSTR 传递到 COM 方法中。为了使代码能够针对 ANSI 和 Unicode 进行相同的编译和工作,我使用 CString::AllocSysString() 来将任何格式的 CString 转换为 Unicode BSTR。

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

目前,我使用 ATL::CComBSTR 进行生命周期管理:

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

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

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

I need to convert a CString instance into a properly allocated BSTR and pass that BSTR into a COM method. To have code that compiles and works indentically for both ANSI and Unicode I use CString::AllocSysString() to convert whatever format CString to a 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.

Currently I use ATL::CComBSTR for lifetime management:

 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::CComBSTR bound to the convertion result.

Is there a better way to accomplish the same task?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

水中月 2024-08-25 14:29:08

CComBSTR 具有 char*wchar_t* 的重载构造函数,它们会调用您的 SysAllocString()代表。因此,代码片段中的显式分配实际上是不必要的。以下内容也同样有效:

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

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

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

:这同样适用于 _bstr_t 类,如果您不希望依赖于 ATL,则可以使用该类来代替 CComBSTR

CComBSTR has 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:

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

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

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

The same applies to the _bstr_t class, which can be used instead of CComBSTR if you don't want a dependency on the ATL.

惟欲睡 2024-08-25 14:29:08

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

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

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.

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.

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

BSTR/C String conversions are required if:

You are doing COM programming in C/C++
You are writing multiple language applications, such as C++ DLL's accessed by Visual Basic applications.
太阳哥哥 2024-08-25 14:29:08

_bstr_t 构造函数之一允许您简单地附加到现有 BSTR,以便您可以在 CString::AllocSysString 时获得您想要的异常code>BSTR 分配失败。

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

_bstr_t 构造函数文档说:

_bstr_t(
   BSTR bstr,
   bool fCopy 
);

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

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

One of _bstr_t constructors allows you to simply attach to existing BSTR so that you can have the exception that you want from CString::AllocSysString when BSTR allocation fails.

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

The _bstr_t constructor documentation says:

_bstr_t(
   BSTR bstr,
   bool fCopy 
);

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

On the other hand, CComBSTR constructor doesn't seem to have the corresponding signature; although it can be used as well if BSTR allocation failure exception is not really needed, as mentioned by Phil Booth in his answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文