【发布时间】:2011-12-20 23:46:51
【问题描述】:
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;
}
【问题讨论】:
-
GetAt(i)将为您提供CComVariant&类型。因此,您可以将您的fld变量更新为引用类型,并检查您在那里拥有的内容以及为什么该事物没有通过赋值/复制。 -
@RomanR。好的,我像这样
CComVariant &fld = fields.GetAt(i);重写了(1)。工作正常,但我现在不知道如何理解,复制构造函数有什么问题 -
现在你有了
fld变量,你可以检查它了。检查其.vt是否良好且不是垃圾。毕竟这个值对copy是无效的,所以应该是有问题,用调试器应该可以看到。 -
.vt正是问题所在。您的变体是.vt+.punkVal。.punkVal似乎是有效的,但.vt必须类似于VT_UNKNOWN或VT_DISPATCH以便 API 意识到你在那里有一个接口。你似乎有垃圾所以 API 失败了。这就是原因,您最终会遇到原因。 -
您创建了一个
IUnknowns 数组,然后您尝试将其解释为VARIANT数组。这些应该是相同的类型,您想要未知数组,然后将接口打包到 CComVariant 中,然后再将其放入 getter 的数组中,否则调用者将处理接口数组。
标签: c++ visual-c++ com atl safearray