2

简而言之,在以下定义中:

HRESULT GetStuff([in] long count, 
                 [out, size_is(count)] long * a,
                 [out, size_is(count)] long * b);

它用count元素填充a和b,调用者将a和/或b设置为null是否合法?

我想让调用者只查询一组结果,所以可以用

long only_a_s[10];
itf->GetStuff(10, a, 0);

我需要修改 MIDL 声明吗?我不确定指针/指针默认属性如何发挥作用。

注意:单独获取它们是有开销的,但是获取调用者不需要的值也是如此,因此单独的 getter 或总是必须同时获取两者是低于标准的。我知道它确实适用于 inproc / in-apartment 调用,但 MIDL 生成的代理/存根会正确处理吗?

4

1 回答 1

1

您不能将空指针作为参数(也称为顶级指针)传递,因为它们是[ref]默认的。

但是您可以为非顶级指针传入或传出空指针。

IDL 方法定义如下:

HRESULT GetStuffAB([in] long countA,
                   [in] long countB,
                   [out, size_is(, *pItemsA)] long **pA,
                   [out, size_is(, *pItemsB)] long **pB,
                   [out] long *pItemsA,
                   [out] long *pItemsB);

C++ 实现:

HRESULT CMyClass::GetStuffAB(long countA,
                             long countB,
                             long **pA,
                             long **pB,
                             long *pItemsA,
                             long *pItemsB)
{
    // COM stubs will check this for you
    // However, you should (must?) manually check in same apartment calls
    if (!pA) return E_POINTER;
    if (!pB) return E_POINTER;
    if (!pItemsA) return E_POINTER;
    if (!pitemsB) return E_POINTER;

    *pA = nullptr;
    *pB = nullptr;
    *pItemsA = 0L;
    *pItemsB = 0L;

    if (countA < 0) return E_INVALIDARG;
    if (countB < 0) return E_INVALIDARG;

    // Get amount of As into *pItemsA if countA > 0
    // Get amount of Bs into *pItemsB if countB > 0

    if (*pItemsA < 0) return E_FAIL;
    if (*pItemsB < 0) return E_FAIL;

    if (*pItemsA > 0)
    {
        *pA = CoTaskMemAlloc(sizeof(long) * *pItemsA);
        if (!*pA) return E_OUTOFMEMORY;
    }

    if (*pItemsB > 0)
    {
        *pB = CoTaskMemAlloc(sizeof(long) * *pItemsB);
        if (!*pB)
        {
            if (*pA)
            {
                // You should not assume the memory will be freed by the caller
                // in such drastic situations, so free and clear *pA here before returning
                CoTaskMemFree(*pA);
                *pA = nullptr;
            }

            return E_OUTOFMEMORY;
        }
    }

    // Get As into *pA and Bs into *pB
    // Or just copy them if getting the amounts implied getting the items

    // You could just as well always return S_OK
    return (*pItemsA > 0 || *pItemsB > 0) ? S_OK : S_FALSE;
}

未显示您必须自己实现的任何其他代码以获取As 的数量和 s 的数量B,以及As 和Bs 本身。

如果您必须让项目知道金额,并且您没有使用 RAII,则应在返回之前手动释放这些资源。

作为使用CoTaskMemAllocand的替代方法CoTaskMemFree,您可能希望使用 ATL CComHeapPtr,它会自动释放内存 RAII 样式,从而简化您的代码。只需确保您在成功返回之前拨打Detach电话*pA即可*pB

于 2015-01-07T12:27:09.673 回答