Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Packing an array inside a VARIANT (VC++ 6.0) (Series 3 of N)

5.00/5 (2 votes)
15 Aug 2013CPOL 13.2K  
Packing an array inside a VARIANT.

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.

C++
typedef struct MyStructType 
{ 
    int nID ; 
    long lVal ; 
    double dblVal ; 
    TCHAR szBuffer[255]; 
} MyStructType ;

Packing an array of structure inside a Variant

C++
int  PackVariantWithStructArray(short nCnt, VARIANT * pVar ) 
{ 
    // TODO: Add your dispatch handler code here 
    USES_CONVERSION ;
    //Initialize the VARIANT (Type is SAFEARRAY of BYTE) 
    VariantInit(pVar); 
    pVar->vt = VT_ARRAY | VT_UI1 ;
    int nBufferSize = nCnt * sizeof ( MyStructType );
    // Define a safe array of nCnt Item and Starting index as 0 
    SAFEARRAYBOUND safeBounds = { nBufferSize, 0}; 
    
    //Create the Safe Array passing it the bounds 
    SAFEARRAY* pSafeArray = SafeArrayCreate(VT_UI1, 1, &safeBounds);
    //Get a pointer to the array data, This actually increments the array’s lock count) 
    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) ; 
    } 
    // We are done wth populating the array Decrement the lock
     SafeArrayUnaccessData(pSafeArray);
    //Assign our VARIANT out param with the array    
    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:

  1. 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.
  2. creating a safe array of the desired (VT_U1) type.
  3. copying the temporary buffer to the safe array of the variant.
  4. free the memory allocated for temporary buffer. (avoid memory leaks).

Fetching a array of structure from a variant

C++
MyStructType * UnPackVariantWithStructArray(short nCount, VARIANT var ) 
{ 
    MyStructType *pBuffer = (MyStructType *) calloc ( nCount, sizeof (MyStructType)) ;  
    USES_CONVERSION ; 
    SAFEARRAY* pSafeArray  = var.parray ; 
    //Get a pointer to the array data, This actually increments the array’s lock count) 
    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 ); 
    } 
    //    We are done wth populating the array Decrement the array’s lock count 
    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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)