gpt4 book ai didi

c# - 使用 SafeArrayGetElement 正确访问 VT_UNKNOWN 的 SafeArray

转载 作者:行者123 更新时间:2023-11-30 22:48:33 25 4
gpt4 key购买 nike

我们有一个 COM 组件,其实现和接口(interface)定义存在于托管代码中,但由 native 组件驱动。托管组件通过以下方法声明将 SafeArray 返回给 native 代码。

interface IExample {
<return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_UNKNOWN)>
object[] DoSomeOperation()
}

生成的 native 签名正确地将其作为 SafeArray 传回。

在代码审查期间,我们提出了一些关于使用 SafeArrayGetElement 调用结果数组的问题。问题是 SafeArrayGetElement 是否返回一个 IUnknown 实例,它是否是 AddRef'd。本质上它归结为以下哪项是正确的

示例 1:

CComPtr<IUnknown> spUnk;
hr = SafeArrayGetElement(pArray, &bounds, reinterpret_cast<void**>(&spUnk));

示例 2:

IUnknown* pUnk;
hr = SafeArrayGetElement(pArray, &bounds, reinterpret_cast<void**>(&pUnk));

关于这个主题的文档非常薄。它只包括以下行。

If the data element is a string, object, or variant, the function copies the element in the correct way.

正确的定义有点模棱两可。

最佳答案

第一种方法应该是正确的,并且符合整个 COM 中对象的处理,大概您找到的定义假设消费者知道正确的方法。

提到的其他项目需要它。复制 VARIANT 或 SAFEARRAY 在它们包含对象时带有隐式 AddRef()。不过,当存在 VT_BYREF 时,VARIANT 不需要它。

VariantCopy @ MSDN
SafeArrayCopy @ MSDN

此行为不是 SAFEARRAY 或 VARIANT 固有的,因为它是 COM 中处理参数的规则的一部分。不过,没有什么能阻止某人试图规避规则。

对于输入参数,AddRef() 的调用方不负责,除非他们打算保留接口(interface)指针以供进一步使用。但是,其他参数使用情况需要它。

例如,放置在 VARIANT 或其他容器中的接口(interface)应该至少应用一个 AddRef() 调用,否则在使用 VARIANT 作为 COM 方法的输出参数时会产生问题,因为数据/引用的传输是单向的。原始对象可能会在调用到达目的地时过期。同样,将接口(interface)编码到 Stream 中也需要 AddRef()。

同样,通过引用调用也需要至少一个 AddRef 调用。如果不是这种情况,则任何合适的长时间运行的调用(例如,通过 DCOM)可能无法到达其目的地,并保证所引用的对象仍然存在。不过,这里经常跳过额外的 AddRef()/Release() 调用,因为由于在调用范围内或之前创建,对象应该已经处于 1+。

如果可以修改组件,并且您的调用正在进行中,那么最好改用 GIT。这允许您改为传递 token ,并且更容易在 COM 单元之间编码接口(interface)。在整个调用期间,所涉及对象的生命周期成为调用者的责任,并且您将能够捕获无法编码(marshal)对象的情况。

Creating the Global Interface Table @ MSDN

同样有趣的是 BSTR 的脚注。

If the implementation of a function that takes a BSTR reference parameter assigns a new BSTR to the parameter, it must free the previously referenced BSTR.

String Manipulation Functions (COM)

关于c# - 使用 SafeArrayGetElement 正确访问 VT_UNKNOWN 的 SafeArray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1609025/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com