Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
COM接口(MIDL):size_用于可选的[out]参数_Com_Midl - Fatal编程技术网

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

COM接口(MIDL):size_用于可选的[out]参数,com,midl,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,

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

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或总是必须同时获取这两个getter都是不够的。我知道它确实适用于inproc/in-plant调用,但是MIDL生成的代理/存根能正确处理这个问题吗

不能将空指针作为参数传递(也称为顶级指针),因为默认情况下它们是空指针

但对于非顶级指针,可以传入或传出空指针

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;
}
HRESULT CMyClass::getStuffLab(长计数),
长countB,
龙**帕,
长**pB,
长*皮特姆萨,
长*pItemsB)
{
//COM存根将为您检查此项
//但是,您应该(必须?)手动签入相同的公寓呼叫
如果(!pA)返回E_指针;
如果(!pB)返回E_指针;
如果(!pItemsA)返回E_指针;
如果(!pitemsB)返回E_指针;
*pA=零PTR;
*pB=零PTR;
*皮特姆萨=0升;
*pItemsB=0L;
如果(countA<0)返回E_INVALIDARG;
如果(countB<0)返回E_INVALIDARG;
//如果countA>0,则将As的量输入*pItemsA
//如果countB>0,则将B的数量输入*pItemsB
如果(*pItemsA<0)返回E_FAIL;
如果(*pItemsB<0)返回E_FAIL;
如果(*pItemsA>0)
{
*pA=CoTaskMemAlloc(长尺寸)**pItemsA;
如果(!*pA)返回E_out内存;
}
如果(*pItemsB>0)
{
*pB=CoTaskMemAlloc(长尺寸)**pItemsB;
如果(!*pB)
{
如果(*pA)
{
//您不应该假定调用者将释放内存
//在如此激烈的情况下,在返回之前,请自由和清晰地在这里广播
CoTaskMemFree(*pA);
*pA=零PTR;
}
返回E_OUTOFMEMORY;
}
}
//将As和Bs分别放入*pA和*pB
//或者,如果得到的金额意味着得到了物品,就复制它们
//你也可以随时返回S_OK
return(*pItemsA>0 | |*pItemsB>0)?S|u OK:S|u FALSE;
}
未显示的是您必须自己实现的任何其他代码,以获得
A
s和
B
s的数量,以及
A
s和
B
s本身

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


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

我建议您定义三种方法,一种用于
a
,一种用于
b
,另一种用于
a
b
,这样您就不必按照自己的方式思考空指针。另外,
HRESULT GetStuffA([in]长计数,[out,size_是(,*pItems)]长**pA,[out]长*pItems)
允许您请求金额,但实际返回的金额不同,通常等于或小于请求的金额,其中被调用方使用
CoTaskMemAlloc
分配数组,调用方使用
CoTaskMemFree
释放数组。