This is the third post about variant, in this post I I am going to explain, how an array of structures can be packed inside a
VARIANT
variable. suppose we have a structure as definition shown below.
typedef struct MyStructType
{
int nID ;
long lVal ;
double dblVal ;
TCHAR szBuffer[255];
} MyStructType ;
Packing an array of structure inside a Variant
int PackVariantWithStructArray(short nCnt, VARIANT * pVar )
{
USES_CONVERSION ;
VariantInit(pVar);
pVar->vt = VT_ARRAY | VT_UI1 ;
int nBufferSize = nCnt * sizeof ( MyStructType );
SAFEARRAYBOUND safeBounds = { nBufferSize, 0};
SAFEARRAY* pSafeArray = SafeArrayCreate(VT_UI1, 1, &safeBounds);
MyStructType * structArray = NULL;
SafeArrayAccessData(pSafeArray, (void**)&structArray);
for ( int i = 0 ; i < nCnt ; i++ )
{
CString strTmp ;
strTmp.Format ( _T("This is Item %2d"), i );
structArray[i].dblVal = (i +1) * 101.0 ;
structArray[i].lVal = (i +1) * 11 ;
structArray[i].nID = (i +1) ;
_tcscpy ( structArray[i].szBuffer, strTmp) ;
}
SafeArrayUnaccessData(pSafeArray);
pVar->parray = pSafeArray ;
return nCnt ;
}
As it can be seen from the above code, here I have just created a byte buffer sufficient to accommodate the all structures,
It involves the following steps:
- Allocating the desired temporary buffer space to hold the array of structures (that should be equivalent to (number of structure x size of structure), and filling that array with values one need to return.
- creating a safe array of the desired (
VT_U1)
type. - copying the temporary buffer to the safe array of the variant.
- free the memory allocated for temporary buffer. (avoid memory leaks).
Fetching a array of structure from a variant
MyStructType * UnPackVariantWithStructArray(short nCount, VARIANT var )
{
MyStructType *pBuffer = (MyStructType *) calloc ( nCount, sizeof (MyStructType)) ;
USES_CONVERSION ;
SAFEARRAY* pSafeArray = var.parray ;
MyStructType *structArray = NULL ;
SafeArrayAccessData ( pSafeArray, (void**)&structArray );
for ( int i = 0 ; i < nCount ; i++ )
{
pBuffer[ i].dblVal = structArray [i].dblVal ;
pBuffer[ i].lVal = structArray [i].lVal ;
pBuffer[ i].nID = structArray [i].nID ;
pBuffer[ i].dblVal = structArray [i].dblVal ;
_tcscpy ( pBuffer[ i].szBuffer, structArray [i].szBuffer );
}
SafeArrayUnaccessData(pSafeArray);
return pBuffer ;
}
This is a crude method, although there is a better method using type libraries, that I will explain in some other article.