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
}
Line (1): fields.GetAt(i)
returns CComVariant
. When I try to assign this value to CComVariant fld
called copy constructor and method CComVariant::Copy
inside the copy constructor. It raise an exception ("bad variable type", DISP_E_BADVARTYPE (0x80020008L)
).
At the same time the line (2) works well. What's wrong with line (1), and how to fix it.
EDIT: This is code for get_Field
(filling 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;
}
You create an array of
IUnknown
s and then you are trying to interpret is as array ofVARIANT
. Those should be the same types, you want either array of unknowns and you pack interface intoCComVariant
before putting it into array in the getter, or otherwise caller will deal with array of interfaces.
As you discovered a mismatch between actual array element type and the type you are casting it to, you will need to update your getter implementation and caller code to match one another.
My personal preference is to create an array of variants, VT_ARRAY | VT_VARIANT
and put the array into [out] VARIANT*
argument. The caller would unwind it back from variant to array, check array type, and then obtain the elements. This is a minimal overhead, and the code around VARIANT
type is best - on the average - in terms of interoperability (in your particular case you definitely might be good with raw types, and without variants at all).