2011-11-03 5 views
2
を反復
CComSafeArray<VARIANT> fields; 
hr = _tab_file->get_Fields(fields.GetSafeArrayPtr()); 

for (LONG i = fields.GetLowerBound(), ie = fields.GetUpperBound(); i <= ie; ++i) 
{ 
    CComVariant fld = fields.GetAt(i); // (1) raises DISP_E_BADVARTYPE (0x80020008L) 

    // Next code works fine     
    CComQIPtr<ITabField> field = fields.GetAt(i).punkVal; // (2) Ok 
    _bstr_t fieldName; 
    hr = field->get_Name(fieldName.GetAddress()); 
    ::OutputDebugString(fieldName + _T("\n")); // Ok 
} 

ライン(1):fields.GetAt(i)戻りCComVariant。この値をコピーコンストラクタと呼ばれるCComVariant fldに割り当てようとすると、コピーコンストラクタ内でCComVariant::Copyメソッドが呼び出されます。例外を発生させます( "bad variable type"、DISP_E_BADVARTYPE (0x80020008L))。 同時に、ライン(2)はうまく機能します。行(1)の何が問題なのか、それを修正する方法エラー:CComVariant ::コピーで "悪い変数の型" CComSafeArray

EDIT:これはget_FieldSAFEARRAYを充填)するためのコードです。

STDMETHODIMP TabFile::get_Fields(SAFEARRAY** fields) 
{ 
    if(mapInfoFile_ == 0) 
    return E_UNEXPECTED; 
    int fieldCount = getFieldCount(); 
    SAFEARRAY* arr = ::SafeArrayCreateVector(VT_UNKNOWN, 0, fieldCount); 
    for(LONG i = 0; i < fieldCount; i++) 
    { 
    QField* field = getQField(i); 
    ITabField* tabField = TabField::CreateInstance(); 
    tabField->put_Name(_bstr_t(field->GetNameRef())); 
    tabField->put_Type(field->GetNativeFieldType(i)); 
    ::SafeArrayPutElement(arr, &i, tabField); 
    tabField->Release(); 
    } 
    *fields = arr; 
    return S_OK; 
} 
+0

'GetAt(i)'はあなたに 'CComVariant&'型を与えます。したがって、 'fld'変数を参照型に更新し、そこに何があるのか​​、なぜ物が代入/複製を使わないのかを確認できます。 @RomanR。 –

+0

[OK]を、私は(CComVariant&fld = fields.GetAt(i);のように)書き直しました。うまく動作しますが、私は現在どのように理解するのか分かりません。コピーコンストラクタの問題は何ですか? – Loom

+2

これで 'fld'変数があり、それを検査することができます。その '.vt'が良好で、迷惑でないかどうか確認してください。結局のところ、この値はコピーには有効ではないので、何か問題があり、デバッガでそれを見ることができるはずです。 –

答えて

2

You create an array of IUnknown s and then you are trying to interpret is as array of VARIANT . Those should be the same types, you want either array of unknowns and you pack interface into CComVariant before putting it into array in the getter, or otherwise caller will deal with array of interfaces.

あなたは、実際の配列要素の型と、あなたがそれをキャストしているタイプの間の不整合を発見したとして、あなたはお互いに合わせてゲッターの実装と、発信者コードを更新する必要があります。

私の個人的な好みは、変異体の配列を作成VT_ARRAY | VT_VARIANT[out] VARIANT*引数に配列を置くことです。呼び出し元は、バリアントから配列に戻し、配列の型をチェックして、要素を取得します。これは最小限のオーバーヘッドであり、VARIANT型のコードは、平均して相互運用性の点で最高です(特定のケースでは、生の型を使用すると間違いなく、バリアントがまったくない可能性があります)。

0

私は、典型的なオフバイエラーがあると思います。 ieは最後の1つの要素なので、fields.GetAt(i)i == ieが存在しない要素を返します。 forのループ終了条件でi <= iei < ieに置き換え、動作するかどうか確認してください。

CComVariantコピーコンストラクタがi == ieのために失敗した場合でも、次の割り当てはCComQIPtr<ITabField>コピーコンストラクタは、スプリアスCComVariantpunkVal分野で取得されているものと幸せになる可能性があるため、動作するように見えるかもしれません。

+1

安全な配列の境界は両端にあり、 'GetAt(GetUpperBound())'はOKです。 –

関連する問題