COM接口(MIDL):size_is用于可选的[out]参数

时间:2014-12-05 09:15:59

标签: com midl

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

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声明?我不知道指针/ pointer_default属性如何发挥作用。

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

1 个答案:

答案 0 :(得分:1)

您不能将空指针作为参数传递(a.k.a。顶级指针),因为默认情况下它们是[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;
}

未显示您必须自己实施的任何其他代码,以获取A的数量和B的数量,以及AB s自己。

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

作为使用CoTaskMemAllocCoTaskMemFree的替代方法,您可能希望使用ATL的CComHeapPtr,它将自动释放内存RAII样式,从而简化您的代码。在成功返回之前,请确保将Detach调用*pA*pB