2014-12-05 76 views
2

總之,在以下定義:COM接口(MIDL):size_is用於可選的[OUT]參數

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

填充a和b與計數元件,是它合法的呼叫者來設置和/或b爲空?

我想允許呼叫者僅查詢一個結果集,所以該方法可以

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

叫我是否需要修改MIDL聲明?我不明白指針/ pointer_default屬性如何發揮到這一點。

注:有開銷分別收購他們,但這樣的收購值調用者不需要,所以單獨干將或總是要同時獲得是低於平均水平。我知道它適用於inproc/in-apartment調用,但MIDL生成的代理/存根會正確處理嗎?

+0

我建議你定義了三種方法,一個是'了',一個是'B',一個用於'了'和'B',所以你不必砍自己的方式思考空指針。此外,'HRESULT GetStuffA([IN]長數,[OUT,size_is(* pItems)]長** pA的,[OUT]長* pItems);'可以請求的量,但實際上返回不同的量,通常等於或小於請求者,被調用者用'CoTaskMemAlloc'分配數組,調用者用'CoTaskMemFree'釋放它。 – acelent 2014-12-06 01:25:58

回答

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; 
} 

並沒有展示任何其他代碼,你必須實現自己獲得的A S中的量和金額的B s,和A s和B s自己。

如果你必須拿到物品後知道金額,以及你不使用RAII,你應該在返回前手動釋放這些資源。

作爲替代使用CoTaskMemAllocCoTaskMemFree,您可能需要使用ATL的CComHeapPtr,它會自動釋放內存RAII風格,從而簡化你的代碼。只要確保在成功返回之前將Detach撥入*pA*pB即可。