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
释放数组。