错误:CComVariant :: Copy中的“错误变量类型”在迭代CComSafeArray时出现

时间:2011-11-03 08:55:56

标签: c++ visual-c++ com atl safearray

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时。它引发异常(“坏变量类型”,DISP_E_BADVARTYPE (0x80020008L))。 同时线(2)运行良好。第(1)行有什么问题,以及如何解决它。

编辑:这是get_Field的代码(填充SAFEARRAY)。

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

2 个答案:

答案 0 :(得分:2)

  

您创建了一个IUnknown的数组,然后您正在尝试解释   是VARIANT的数组。那些应该是你想要的相同类型   无论是未知数组还是将接口打包到CComVariant   在将其放入getter中的数组之前,或者以其他方式调用者   处理接口数组。

当您发现实际数组元素类型与您将其转换为的类型不匹配时,您需要更新您的getter实现和调用者代码以使其彼此匹配。

我个人的偏好是创建一个变种数组VT_ARRAY | VT_VARIANT并将数组放入[out] VARIANT*参数中。调用者将它从variant变回数组,检查数组类型,然后获取元素。这是一个最小的开销,并且VARIANT类型的代码最好 - 平均而言 - 在互操作性方面(在您的特定情况下,您肯定可能对原始类型很好,并且根本没有变体)。

答案 1 :(得分:0)

我认为你有一个典型的逐个错误。 ie是最后一个元素之后的一个元素,因此fields.GetAt(i) i == ie将返回一个不存在的元素。尝试在i <= ie循环终止条件中将i < ie替换为for,看看它是否有效。

即使CComVariant复制构造函数对i == ie失败,下一个作业似乎也可行,因为CComQIPtr<ITabField>复制构造函数可能对{{1}处检索到的内容感到满意伪造的punkVal字段。