3

(i) COM 境界を越えて long の safearray を取得し、(ii) 便宜上 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);
4

1 に答える 1

3

if(newVal.vt | (VT_ARRAY & VT_I4))

これは、あなたが思っているようには機能しません。この条件は常に true です。あなたは探しているif (newVal.vt == VT_ARRAY | VT_I4)

ではput_EligibleProductsAttachCComSafeArray を VARIANT 内のポインターに編集しましたが、デタッチしていません。範囲外にwrapperなると、セーフ配列が破棄されます。次に、呼び出し元は を使用して 2 回目の破棄を試みVariantClearます。これがあなたの困難の直接の原因です。

于 2013-07-15T23:08:58.610 に答える