我们应该将 COM 中的 BSTR 类型视为值还是引用?

2023-12-25

来自书本ATL内部结构,我知道BSTR与OLECHAR*不同,BSTR有CComBSTR和CString。

根据MSDN为 BSTR 分配和释放内存 http://msdn.microsoft.com/en-us/library/vstudio/xda6xzx7%28v=vs.110%29.aspx,我知道调用者/被调用者的内存管理责任。

从 MSDN 中获取这一行,

HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)

我还是不知道如何处理bstr在我的实施中正确地执行。因为我对 BSTR 仍然有一个基本问题——我们应该治疗吗?bstr作为值(如 int)或作为引用(如 int*),至少在 COM 接口边界上。

我想在我的实现中尽快将 BSTR 转换为 CString/CComBSTR。值或引用语义对于转换来说将是完全不同的情况。我深入研究了CComBSTR.Attach、CComBSTR.AssignBSTR等,但代码无法解决我的疑问。

MSDN CComBSTR.Attach 有一些代码片段,我觉得它是错误的,因为它不遵守为 BSTR 分配和释放内存 http://msdn.microsoft.com/en-us/library/vstudio/xda6xzx7%28v=vs.110%29.aspx。 ATL Internals 表示 SetSysString 将“释放传入的原始 BSTR”,如果我使用它,它将违反 BSTR 参数约定,就像 CComBSTR.Attach 一样。

总而言之,我想在实现中使用 CString 来处理原始 BSTR,但不知道正确的方法...我在我的项目中编写了一些只是工作的代码,但我总是感到紧张,因为我不知道是否我是对的。

让我谈谈编码语言

HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)
{
// What I do NOT know
CString str1;  // 1. copy bstr (with embeded NUL)
CString str2;  // 2. ref bstr

// What I know
CComBSTR cbstr1;
cbstr1.AssignBSTR(bstr); // 3. copy bstr 
CComBSTR cbstr2;
cbstr2.Attach(bstr); // 4. ref bstr, do not copy

// What I do NOT know
// Should we copy or ref bstr ???
}

CComBSTR只是一个RAII 包装器 http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization around raw BSTR。所以请放心使用CComBSTR而不是原始的BSTR帮助编写异常安全的代码,这使得泄漏资源(即原始 BSTR)变得更加困难,等等。

If the BSTR is an input参数,它就像一个const wchar_t*(带有长度前缀,并且可能有一些NULs L'\0'里面的字符)。如果BSTR没有NULs 嵌入内部,您可以简单地将其传递给CString构造函数,这将对其进行深层复制,并且您可以在本地使用您的CString。对此的修改CString在原件上将不可见BSTR。您也可以使用 std::wstring (并注意std::wstring可以处理嵌入式NUL也是如此)。

void DoSomething(BSTR bstrInput)
{
    std::wstring myString(bstrInput);
    // ... work with std::wstring (or CString...) inside here
}

相反,如果BSTR is an output参数,然后使用另一级间接传递,即BSTR*。在这种情况下,您可以使用CComBSTR::Detach()在你的方法中释放BSTR安全地包裹在CComBSTR,并将其所有权转移给调用者:

HRESULT DoSomething( BSTR* pbstrOut )
{
    // Check parameter pointer
    if (pbstrOut == nullptr)
        return E_POINTER;

    // Guard code with try-catch, since exceptions can't cross COM module boundaries.
    try
    {
        std::wstring someString;
        // ... work with std::wstring (or CString...) inside here

        // Build a BSTR from the ordinary string     
        CComBSTR bstr(someString.c_str());

        // Return to caller ("move semantics", i.e. transfer ownership
        // from current CComBSTR to the caller)
        *pbstrOut = bstr.Detach();

        // All right
        return S_OK;
    }
    catch(const std::exception& e)
    {
        // Log exception message...
        return E_FAIL;
    }
    catch(const CAtlException& e)
    {
        return e; // implicit cast to HRESULT
    }
}

基本上,这个想法是使用BSTR(封装在 RAII 类中,例如CComBSTR) only 在边界处,并使用进行本地工作std::wstring or CString.

作为“奖励阅读”,请考虑Eric Lippert 的 BSTR 语义指南 http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我们应该将 COM 中的 BSTR 类型视为值还是引用? 的相关文章

  • 如何获取正在访问 ASP.NET 应用程序的当前用户?

    为了获取系统中当前登录的用户 我使用以下代码 string opl System Security Principal WindowsIdentity GetCurrent Name ToString 我正在开发一个 ASP NET 应用程
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur

随机推荐

  • 是否可以在javascript中创建固定长度的数组?

    在Javascript中 是否可以创建一个保证长度保持不变的数组 例如 数组A创建的长度为 2 随后 任何调用的尝试A push or A pop 或设置值A 5 将失败 A length永远是 2 这是输入数组的方式 例如Float32A
  • 选择列表框中的项目后打开新表单

    我的表单上有一个列表框和一个按钮 列表框包含 3 个元素 房屋 人物 户外 我还创建了 3 个表单来表示列表框中的值 我希望用户突出显示列表框中的项目 单击按钮后我想打开用户选择的表单 我怎样才能实现这个目标 我已经尝试过这个链接 通过单击
  • groovy 脚本中提供的名称无效(机制级别:KrbException:无法找到默认领域)

    我有一个连接到 MSSQL 数据库的 groovy 脚本 几周前它工作得很好 但今天我上传了 mac os 的最后一个版本 我的脚本给了我这个例外 Caught java sql SQLException I O Error GSS Fai
  • d3.js:强制布局中建议的节点位置

    我想创建一个图表 其中节点具有建议的位置 但我也想使用力布局来确保节点本身不重叠 这在d3中可能吗 是的 您可以通过以下方式执行此操作 禁用默认的重力和电荷力 实施碰撞检测 http mbostock github com d3 talk
  • Dockerhub 的访问令牌

    我创建了一个存储库hub docker com现在想要使用我的凭据将我的映像推送到 Dockerhub 我想知道是否必须使用我的用户名和密码 或者是否可以创建某种访问令牌来推送 docker 映像 我想做的是使用docker image来自
  • 如何找到 php_smart_string.h 而不是 php_smart_str.h?

    It s me tmp pear install inclued 0 1 3 make bin bash tmp pear install inclued 0 1 3 libtool mode compile cc I I tmp pear
  • 创建 DLL 以在两个进程之间共享内存

    我需要使用 DLL 来实现类似于 Linux 共享内存的功能 我的Windows编程经验很少 但我认为有可能实现我的目标 我想要类似下面的东西 DLL int x void write int temp x temp int read re
  • Webpack 错误:请手动安装 sqlite3 包

    我正在使用 Electron 和 Sequelize 构建一个应用程序 我开始配置数据库 然后 我收到此错误 未捕获的错误 请手动安装 sqlite3 包 在新的 ConnectionManager home matheusdrdj Doc
  • 快速递增 Int!不工作

    我理解选项是如何工作的 但这让我陷入了困境 我有一个变量叫做num我想增加它 所以我做了以下操作 var num Int 0 num ERROR Unary operator cannot be applied to an operand
  • 如何在 Playground 中运行异步回调

    许多 Cocoa 和 CocoaTouch 方法都具有在 Objective C 中作为块实现的完成回调以及在 Swift 中作为闭包实现的回调 然而 当在 Playground 中尝试这些时 永远不会调用完成 例如 Playground
  • 如何在Android中以编程方式从网络下载文件?

    在我的应用程序中 从 Web 下载大量文件 这些文件大小约为 200Mb 已压缩 如何在 Android 中以编程方式下载文件 实际上我关心的是代码的性能 如何处理其间的错误和网络问题 这是我最近为此编写的一些代码 try URL u ne
  • 来自 sqlalchemy 的 psycopg2 register_composite

    是否可以以某种方式使用函数注册复合材料 http initd org psycopg docs extras html psycopg2 extras register composite来自 psycopg2 当我使用 sqlalchem
  • 有没有办法可以将 FormattedText 包含在 Xamarin.Forms 的 .alert 中?

    我有一个格式化的字符串 在代码中 它不止于此 但这只是一个示例 var fs new FormattedString fs fs Spans Add new Span Text ABC ForegroundColor Color FromH
  • 将 Inno Setup 中许可证向导页面上的单选按钮替换为复选框

    有没有简单的方法可以用 Inno Setup 中的单个 选中 未选中 复选框替换许可证向导页面上的标准 2 个单选按钮 而无需创建自定义页面 由于没有设置可以在许可证单选按钮和某些许可证复选框之间切换 至少只是因为在WizardForm 你
  • 虚函数和 std::function?

    考虑以下 C 17 代码 include
  • Firebase Firestore子集合安全查询

    我的 Cloud Firestore 数据库中有以下规则 service cloud firestore match databases database documents match performances performanceId
  • 读取不确定的值是未定义的行为吗?

    该问题出现在该问题答案的评论中当类型转换为 int 时 C C bool 类型是否始终保证为 0 或 1 https stackoverflow com questions 4276207 is c c bool type always g
  • 将 pandas 数据框插入 Postgres

    我有一个 pandas 数据框 我想将其插入到 Django 项目中的 Postgres 数据库中 数据框有5列 数据库表有6列 而且数据框列和数据库列顺序不同 那么 在合并两者之前 我是否必须确保数据框和数据库表中的列顺序相同 请建议我如
  • SAS 无法识别日期格式

    我有以下字符日期格式 3 1990 4 1990 5 1990 我尝试了以下代码 data work temps set indata newdate input strip Date MMYYSw rename newdate date
  • 我们应该将 COM 中的 BSTR 类型视为值还是引用?

    来自书本ATL内部结构 我知道BSTR与OLECHAR 不同 BSTR有CComBSTR和CString 根据MSDN为 BSTR 分配和释放内存 http msdn microsoft com en us library vstudio