2013-07-15 33 views
2

我試圖(i)爲了方便起見跨越COM邊界獲得longarray的safearray,並(ii)使用CComSafeArray。跨COM邊界傳遞CComSafeArray

我的問題是,設置COM屬性後發生意外不可預知的崩潰(請參閱下面的pPrologue-> EligibleProducts = var;)。我發現很難理解如何從Microsoft文檔中使用CComSafeArray,任何人都可以擺脫困境嗎?先謝謝你!

在IDL我:

[propget, id(1), helpstring("property EligibleProducts")] HRESULT EligibleProducts([out, retval] VARIANT* pVal); 
[propput, id(1), helpstring("property EligibleProducts")] HRESULT EligibleProducts([in] VARIANT newVal); 

我的服務器代碼:

STDMETHODIMP CPrologue::put_EligibleProducts(VARIANT newVal) 
{ 
    HRESULT hr = E_FAIL; 

    AFX_MANAGE_STATE(AfxGetStaticModuleState()) 

    //start by clearing out any existing data 
    m_EligibleProducts.clear(); 

    if(newVal.vt | (VT_ARRAY & VT_I4)) 
    { 
     //construct a wrapper class with the passed in SAFEARRAY 
     CComSafeArray<long> wrapper; 
     wrapper.Attach(newVal.parray); 

     int iProductID = 0; 

     //loop through products and add them to our vector 
     int iCount = wrapper.GetCount(); 
     for(int iIndex = 0; iIndex < iCount; iIndex++) 
     { 
      iProductID = wrapper.GetAt(iIndex); 
      if(iProductID > 0) 
      { 
       m_EligibleProducts.push_back(iProductID); 
      } 
     } 

     hr = S_OK; 

    return hr; 
} 

我的調用代碼是:

   VARIANT var; 
       ::VariantInit(&var); 
       var.vt = VT_ARRAY | VT_I4; 

       CComSafeArray<long> wrapper; 

       for(std::vector<long>::const_iterator it = products.begin(); it != products.end(); it++) 
       { 
        wrapper.Add(*it); 
       } 

       //get the SAFEARRAY from the wrapper 
       var.parray = wrapper.Detach(); 

       //and store it on the appropriate business object 
       IProloguePtr pPrologue = pCustomer->Prologue;  
       **pPrologue->EligibleProducts = var;** 

       //clean up the variant (and hence SAFEARRAY) 
       ::VariantClear(&var); 

回答

3

如果(newVal.vt | (VT_ARRAY & VT_I4))

這不會做你認爲它所做的事情。這種情況總是如此。您正在尋找if (newVal.vt == VT_ARRAY | VT_I4)

put_EligibleProducts,您有 ed CComSafeArray指向VARIANT內的指針,但您尚未分離它。當wrapper超出範圍時,它會銷燬safearray。然後呼叫者嘗試通過VariantClear第二次銷燬它。這是你困難的直接原因。

+0

分離確實解決了問題。事實上,既不附加也不分離工作(即只是將數組傳遞給包裝器構造函數),那麼它不會控制 - 這正是我試圖達到的目的(同樣感謝其他修復)。 –

+0

當您將數組傳遞給構造函數時,「CComSafeArray」將複製數據;然後再銷燬該副本。看看你是否願意承擔這種開銷。 –

+0

再次感謝您的澄清。這裏的表現不是問題,所以我認爲我會堅持做一個副本。也許有時間去掌握ATL內部... –