COleSafeArray Class

A class for working with arrays of arbitrary type and dimension.

Syntax

class COleSafeArray : public tagVARIANT

Members

Public Constructors

Name Description
COleSafeArray::COleSafeArray Constructs a COleSafeArray object.

Public Methods

Name Description
COleSafeArray::AccessData Retrieves a pointer to the array data.
COleSafeArray::AllocData Allocates memory for the array.
COleSafeArray::AllocDescriptor Allocates memory for the safe array descriptor.
COleSafeArray::Attach Gives control of the existing VARIANT array to the COleSafeArray object.
COleSafeArray::Clear Frees all data in the underlying VARIANT.
COleSafeArray::Copy Creates a copy of an existing array.
COleSafeArray::Create Creates a safe array.
COleSafeArray::CreateOneDim Creates a one-dimensional COleSafeArray object.
COleSafeArray::Destroy Destroys an existing array.
COleSafeArray::DestroyData Destroys data in a safe array.
COleSafeArray::DestroyDescriptor Destroys a descriptor of a safe array.
COleSafeArray::Detach Detaches the VARIANT array from the COleSafeArray object (so that the data will not be freed).
COleSafeArray::GetByteArray Copies the contents of the safe array into a CByteArray.
COleSafeArray::GetDim Returns the number of dimensions in the array.
COleSafeArray::GetElement Retrieves a single element of the safe array.
COleSafeArray::GetElemSize Returns the size, in bytes, of one element in a safe array.
COleSafeArray::GetLBound Returns the lower bound for any dimension of a safe array.
COleSafeArray::GetOneDimSize Returns the number of elements in the one-dimensional COleSafeArray object.
COleSafeArray::GetUBound Returns the upper bound for any dimension of a safe array.
COleSafeArray::Lock Increments the lock count of an array and places a pointer to the array data in the array descriptor.
COleSafeArray::PtrOfIndex Returns a pointer to the indexed element.
COleSafeArray::PutElement Assigns a single element into the array.
COleSafeArray::Redim Changes the least significant (rightmost) bound of a safe array.
COleSafeArray::ResizeOneDim Changes the number of elements in a one-dimensional COleSafeArray object.
COleSafeArray::UnaccessData Decrements the lock count of an array and invalidates the pointer retrieved by AccessData.
COleSafeArray::Unlock Decrements the lock count of an array so it can be freed or resized.

Public Operators

Name Description
COleSafeArray::operator LPCVARIANT Accesses the underlying VARIANT structure of the COleSafeArray object.
COleSafeArray::operator LPVARIANT Accesses the underlying VARIANT structure of the COleSafeArray object.
COleSafeArray::operator = Copies values into a COleSafeArray object (SAFEARRAY, VARIANT, COleVariant, or COleSafeArray array).
COleSafeArray::operator == Compares two variant arrays (SAFEARRAY, VARIANT, COleVariant, or COleSafeArray arrays).
COleSafeArray::operator << Outputs the contents of a COleSafeArray object to the dump context.

Remarks

COleSafeArray derives from the OLE VARIANT structure. The OLE SAFEARRAY member functions are available through COleSafeArray, as well as a set of member functions specifically designed for one-dimensional arrays of bytes.

Inheritance Hierarchy

tagVARIANT

COleSafeArray

Requirements

Header: afxdisp.h

COleSafeArray::AccessData

Retrieves a pointer to the array data.

void AccessData(void** ppvData);

Parameters

ppvData
A pointer to a pointer to the array data.

Remarks

On error, the function throws a CMemoryException or COleException.

Example

void CMainFrame::Sort(VARIANT* vArray)
{
   COleSafeArray sa;
   BSTR* pbstr;
   TCHAR buf[1024];
   LONG cElements, lLBound, lUBound;

   //needed for OLE2T macro below, include afxpriv.h
   USES_CONVERSION;

   // Type check VARIANT parameter. It should contain a BSTR array
   // passed by reference. The array must be passed by reference it is
   // an in-out-parameter.
   if (V_VT(vArray) != (VT_ARRAY | VT_BSTR))
   {
      AfxThrowOleDispatchException(1001,
         _T("Type Mismatch in Parameter. Pass a string array by reference"));
   }

   // clears data in sa and copies the variant data into sa
   sa.Attach(*vArray);

   // Check that array is 1 dimensional
   if (sa.GetDim() != 1)
   {
      AfxThrowOleDispatchException(1002,
         _T("Type Mismatch in Parameter. Pass a one-dimensional array"));
   }

   try
   {
      // Get array bounds.
      sa.GetLBound(1, &lLBound);
      sa.GetUBound(1, &lUBound);

      // Get a pointer to the elements of the array
      // and increments the lock count on the array
      sa.AccessData((LPVOID*)& pbstr);

      //get no. of elements in array
      cElements = lUBound - lLBound + 1;
      for (int i = 0; i < cElements; i++)
      {
         //output the elements of the array
         _stprintf_s(buf, 1024, _T("[%s]\n"), OLE2T(pbstr[i]));
         OutputDebugString(buf);
      }

      //decrement lock count
      sa.UnaccessData();
   }
   catch (COleException* pEx)
   {
      AfxThrowOleDispatchException(1003,
         _T("Unexpected Failure in FastSort method"));
      pEx->Delete();
   }
}

COleSafeArray::AllocData

Allocates memory for a safe array.

void AllocData();

Remarks

On error, the function throws a CMemoryException or COleException.

COleSafeArray::AllocDescriptor

Allocates memory for the descriptor of a safe array.

void AllocDescriptor(DWORD dwDims);

Parameters

dwDims
Number of dimensions in the safe array.

Remarks

On error, the function throws a CMemoryException or COleException.

COleSafeArray::Attach

Gives control of the data in an existing VARIANT array to the COleSafeArray object.

void Attach(VARIANT& varSrc);

Parameters

varSrc
A VARIANT object. The varSrc parameter must have the VARTYPE VT_ARRAY.

Remarks

The source VARIANT's type is set to VT_EMPTY. This function clears the current array data, if any.

Example

See the example for COleSafeArray::AccessData.

COleSafeArray::Clear

Clears the safe array.

void Clear();

Remarks

The function clears a safe array by setting the VARTYPE of the object to VT_EMPTY. The current contents are released and the array is freed.

COleSafeArray::COleSafeArray

Constructs a COleSafeArray object.

COleSafeArray();

COleSafeArray(
    const SAFEARRAY& saSrc,
    VARTYPE vtSrc);

COleSafeArray(
    LPCSAFEARRAY pSrc,
    VARTYPE vtSrc);

COleSafeArray(const COleSafeArray& saSrc);
COleSafeArray(const VARIANT& varSrc);
COleSafeArray(LPCVARIANT pSrc);
COleSafeArray(const COleVariant& varSrc);

Parameters

saSrc
An existing COleSafeArray object or SAFEARRAY to be copied into the new COleSafeArray object.

vtSrc
The VARTYPE of the new COleSafeArray object.

psaSrc
A pointer to a SAFEARRAY to be copied into the new COleSafeArray object.

varSrc
An existing VARIANT or COleVariant object to be copied into the new COleSafeArray object.

pSrc
A pointer to a VARIANT object to be copied into the new COleSafeArray object.

Remarks

All of these constructors create new COleSafeArray objects. If there is no parameter, an empty COleSafeArray object is created (VT_EMPTY). If the COleSafeArray is copied from another array whose VARTYPE is known implicitly (a COleSafeArray, COleVariant, or VARIANT), the VARTYPE of the source array is retained and need not be specified. If the COleSafeArray is copied from another array whose VARTYPE is not known (SAFEARRAY), the VARTYPE must be specified in the vtSrc parameter.

On error, the function throws a CMemoryException or COleException.

COleSafeArray::Copy

Creates a copy of an existing safe array.

void Copy(LPSAFEARRAY* ppsa);

Parameters

ppsa
Pointer to a location in which to return the new array descriptor.

Remarks

On error, the function throws a CMemoryException or COleException.

COleSafeArray::Create

Allocates and initializes the data for the array.

void Create(
    VARTYPE vtSrc,
    DWORD dwDims,
    DWORD* rgElements);

void Create(
    VARTYPE vtSrc,
    DWORD dwDims,
    SAFEARRAYBOUND* rgsabounds);

Parameters

vtSrc
The base type of the array (that is, the VARTYPE of each element of the array). The VARTYPE is restricted to a subset of the variant types. Neither the VT_ARRAY nor the VT_BYREF flag can be set. VT_EMPTY and VT_NULL are not valid base types for the array. All other types are legal.

dwDims
Number of dimensions in the array. This can be changed after the array is created with Redim.

rgElements
Pointer to an array of the number of elements for each dimension in the array.

rgsabounds
Pointer to a vector of bounds (one for each dimension) to allocate for the array.

Remarks

This function will clear the current array data if necessary. On error, the function throws a CMemoryException.

Example

COleSafeArray saMatrix;
DWORD numElements[] = { 10, 5 };

// creates a 2 dimensional safearray of type VT_I2 
// with size 10x5 elements, with all indices starting at 0(default)
saMatrix.Create(VT_I2, 2, numElements);

ASSERT(saMatrix.GetDim() == 2);

COleSafeArray saVector;
SAFEARRAYBOUND rgsabounds[] = { {5, 2} };

// creates a 1 dimensional safearray of type VT_I1 
// with size 5 elements, with the index starting at 2
saVector.Create(VT_I1, 1, rgsabounds);

ASSERT(saVector.GetDim() == 1);

COleSafeArray::CreateOneDim

Creates a new one-dimensional COleSafeArray object.

void CreateOneDim(
    VARTYPE vtSrc,
    DWORD dwElements,
    const void* pvSrcData = NULL,
    long nLBound = 0);

Parameters

vtSrc
The base type of the array (that is, the VARTYPE of each element of the array).

dwElements
Number of elements in the array. This can be changed after the array is created with ResizeOneDim.

pvSrcData
Pointer to the data to copy into the array.

nLBound
The lower bound of the array.

Remarks

The function allocates and initializes the data for the array, copying the specified data if the pointer pvSrcData is not NULL.

On error, the function throws a CMemoryException.

Example

VARIANT varColInfo[3];

//initialize VARIANTs
for (int i = 0; i < 3; i++)
   VariantInit(&varColInfo[i]);

// Column Name
varColInfo[0].vt = VT_BSTR;
varColInfo[0].bstrVal = ::SysAllocString(L"Name");

// Column Type
varColInfo[1].vt = VT_UI4;
varColInfo[1].lVal = 1;

COleSafeArray sa;
//create a 1 dimensional safearray of VARIANTs
//& initialize it with varColInfo VARIANT array
sa.CreateOneDim(VT_VARIANT, 2, varColInfo);

//check that the dimension is 2
ASSERT(sa.GetOneDimSize() == 2);

//increase safearray size by 1
sa.ResizeOneDim(3);

// populate the last element of the safearray, (Column Size)
varColInfo[2].vt = VT_I4;
varColInfo[2].lVal = 30;
long el = 2;
sa.PutElement(&el, &varColInfo[2]);

COleSafeArray::Destroy

Destroys an existing array descriptor and all the data in the array.

void Destroy();

Remarks

If objects are stored in the array, each object is released. On error, the function throws a CMemoryException or COleException.

COleSafeArray::DestroyData

Destroys all the data in a safe array.

void DestroyData();

Remarks

If objects are stored in the array, each object is released. On error, the function throws a CMemoryException or COleException.

COleSafeArray::DestroyDescriptor

Destroys a descriptor of a safe array.

void DestroyDescriptor();

Remarks

On error, the function throws a CMemoryException or COleException.

COleSafeArray::Detach

Detaches the VARIANT data from the COleSafeArray object.

VARIANT Detach();

Return Value

The underlying VARIANT value in the COleSafeArray object.

Remarks

The function detaches the data in a safe array by setting the VARTYPE of the object to VT_EMPTY. It is the caller's responsibility to free the array by calling the Windows function VariantClear.

On error, the function throws a COleException.

Example

See the example for COleSafeArray::PutElement.

COleSafeArray::GetByteArray

Copies the contents of the safe array into a CByteArray.

void GetByteArray(CByteArray& bytes);

Parameters

bytes
A reference to a CByteArray object.

COleSafeArray::GetDim

Returns the number of dimensions in the COleSafeArray object.

DWORD GetDim();

Return Value

The number of dimensions in the safe array.

Example

COleSafeArray saMatrix;
DWORD numElements[] = { 10, 5 };

// creates a 2 dimensional safearray of type VT_I2 
// with size 10x5 elements, with all indices starting at 0(default)
saMatrix.Create(VT_I2, 2, numElements);

ASSERT(saMatrix.GetDim() == 2);

COleSafeArray saVector;
SAFEARRAYBOUND rgsabounds[] = { {5, 2} };

// creates a 1 dimensional safearray of type VT_I1 
// with size 5 elements, with the index starting at 2
saVector.Create(VT_I1, 1, rgsabounds);

ASSERT(saVector.GetDim() == 1);

COleSafeArray::GetElement

Retrieves a single element of the safe array.

void GetElement(
    long* rgIndices,
    void* pvData);

Parameters

rgIndices
Pointer to an array of indexes for each dimension of the array.

pvData
Pointer to the location to place the element of the array.

Remarks

This function automatically calls the windows functions SafeArrayLock and SafeArrayUnlock before and after retrieving the element. If the data element is a string, object, or variant, the function copies the element in the correct way. The parameter pvData should point to a large enough buffer to contain the element.

On error, the function throws a CMemoryException or COleException.

Example

//sa is of type COleSafeArray with 2 dimensions

//Determine upper bounds for both dimensions
long lNumRows;
long lNumCols;
sa.GetUBound(1, &lNumRows);
sa.GetUBound(2, &lNumCols);

//Display the elements in the SAFEARRAY.
long index[2];
VARIANT val;

//Determine lower bounds for both dimensions
long lowRow, lowCol;
sa.GetLBound(1, &lowRow);
sa.GetLBound(2, &lowCol);

for (long r = lowRow; r <= lNumRows; r++)
{
   for (long c = lowCol; c <= lNumCols; c++)
   {
      index[0] = r;
      index[1] = c;

      //retrieve each element of the safearray
      sa.GetElement(index, &val);

      switch (val.vt)
      {
      case VT_R8:
         TRACE(_T("%1.2f\n"), val.dblVal);
         break;

      case VT_BSTR:
         TRACE(_T("%s\n"), (CString)val.bstrVal);
         break;

         // other cases omitted

      case VT_EMPTY:
         TRACE(_T("<empty>\n"));
         break;
      }
   }
}

COleSafeArray::GetElemSize

Retrieves the size of an element in a COleSafeArray object.

DWORD GetElemSize();

Return Value

The size, in bytes, of the elements of a safe array.

COleSafeArray::GetLBound

Returns the lower bound for any dimension of a COleSafeArray object.

void GetLBound(
    DWORD dwDim,
    long* pLBound);

Parameters

dwDim
The array dimension for which to get the lower bound.

pLBound
Pointer to the location to return the lower bound.

Remarks

On error, the function throws a COleException.

Example

COleSafeArray saMatrix;
DWORD numElements[] = { 10, 5 };

// creates a 2 dimensional safearray of type VT_I2 
// with size 10x5 elements, with all indices starting at 0(default)
saMatrix.Create(VT_I2, 2, numElements);

long lLBound;

//get lower bound for 1st dimension
saMatrix.GetLBound(1, &lLBound);

ASSERT(lLBound == 0);

//get lower for 2nd dimension
saMatrix.GetLBound(2, &lLBound);

ASSERT(lLBound == 0);

COleSafeArray saVector;
SAFEARRAYBOUND rgsabounds[] = { {5, 1} };

// creates a 1 dimensional safearray of type VT_I1 
// with size 5 elements, with the index starting at 1
saVector.Create(VT_I1, 1, rgsabounds);

//get lower bound for 1st dimension
saVector.GetLBound(1, &lLBound);

ASSERT(lLBound == 1);

COleSafeArray::GetOneDimSize

Returns the number of elements in the one-dimensional COleSafeArray object.

DWORD GetOneDimSize();

Return Value

The number of elements in the one-dimensional safe array.

Example

See the example for COleSafeArray::CreateOneDim.

COleSafeArray::GetUBound

Returns the upper bound for any dimension of a safe array.

void GetUBound(
    DWORD dwDim,
    long* pUBound);

Parameters

dwDim
The array dimension for which to get the upper bound.

pUBound
Pointer to the location to return the upper bound.

Remarks

On error, the function throws a COleException.

Example

COleSafeArray saMatrix;
DWORD numElements[] = { 10, 5 };

// creates a 2 dimensional safearray of type VT_I2 
// with size 10x5 elements, with all indices starting at 0(default)
saMatrix.Create(VT_I2, 2, numElements);

long lUBound;
ASSERT(saMatrix.GetDim() == 2);

//get upper bound for 1st dimension
saMatrix.GetUBound(1, &lUBound);

ASSERT(lUBound == 9);

//get upper bound for 2nd dimension
saMatrix.GetUBound(2, &lUBound);

ASSERT(lUBound == 4);

COleSafeArray saVector;
SAFEARRAYBOUND rgsabounds[] = { {5, 1} };

// creates a 1 dimensional safearray of type VT_I1 
// with size 5 elements, with the index starting at 1
saVector.Create(VT_I1, 1, rgsabounds);

//get upper bound for 1st dimension
saVector.GetUBound(1, &lUBound);

ASSERT(lUBound == 5);

COleSafeArray::Lock

Increments the lock count of an array and place a pointer to the array data in the array descriptor.

void Lock();

Remarks

On error, it throws a COleException.

The pointer in the array descriptor is valid until Unlock is called. Calls to Lock can be nested; an equal number of calls to Unlock are required.

An array cannot be deleted while it is locked.

COleSafeArray::operator LPCVARIANT

Call this casting operator to access the underlying VARIANT structure for this COleSafeArray object.

operator LPCVARIANT() const;

COleSafeArray::operator LPVARIANT

Call this casting operator to access the underlying VARIANT structure for this COleSafeArray object.

operator LPVARIANT();

Remarks

Note that changing the value in the VARIANT structure accessed by the pointer returned by this function will change the value of this COleSafeArray object.

COleSafeArray::operator =

These overloaded assignment operators copy the source value into this COleSafeArray object.

COleSafeArray& operator=(const COleSafeArray& saSrc);
COleSafeArray& operator=(const VARIANT& varSrc);
COleSafeArray& operator=(LPCVARIANT pSrc);
COleSafeArray& operator=(const COleVariant& varSrc);

Remarks

A brief description of each operator follows:

  • operator =( saSrc ) Copies an existing COleSafeArray object into this object.

  • operator =( varSrc ) Copies an existing VARIANT or COleVariant array into this object.

  • operator =( pSrc ) Copies the VARIANT array object accessed by pSrc into this object.

COleSafeArray::operator ==

This operator compares two arrays (SAFEARRAY, VARIANT, COleVariant, or COleSafeArray arrays) and returns nonzero if they are equal; otherwise 0.

BOOL operator==(const SAFEARRAY& saSrc) const;  BOOL operator==(LPCSAFEARRAY pSrc) const;

BOOL operator==(const COleSafeArray& saSrc) const;  BOOL operator==(const VARIANT& varSrc) const;

BOOL operator==(LPCVARIANT pSrc) const;  BOOL operator==(const COleVariant& varSrc) const;

Remarks

Two arrays are equal if they have an equal number of dimensions, equal size in each dimension, and equal element values.

COleSafeArray::operator <<

The COleSafeArray insertion (<<) operator supports diagnostic dumping and storing of a COleSafeArray object to an archive.

CDumpContext& AFXAPI operator<<(
    CDumpContext& dc,
    COleSafeArray& saSrc);

COleSafeArray::PtrOfIndex

Returns a pointer to the element specified by the index values.

void PtrOfIndex(
    long* rgIndices,
    void** ppvData);

Parameters

rgIndices
An array of index values that identify an element of the array. All indexes for the element must be specified.

ppvData
On return, pointer to the element identified by the values in rgIndices.

COleSafeArray::PutElement

Assigns a single element into the array.

void PutElement(
    long* rgIndices,
    void* pvData);

Parameters

rgIndices
Pointer to an array of indexes for each dimension of the array.

pvData
Pointer to the data to assign to the array. VT_DISPATCH, VT_UNKNOWN, and VT_BSTR variant types are pointers and do not require another level of indirection.

Remarks

This function automatically calls the Windows functions SafeArrayLock and SafeArrayUnlock before and after assigning the element. If the data element is a string, object, or variant, the function copies it correctly, and if the existing element is a string, object, or variant, it is cleared correctly.

Note that you can have multiple locks on an array, so you can put elements into an array while the array is locked by other operations.

On error, the function throws a CMemoryException or COleException.

Example

VARIANT retVariantArray()
{
   COleSafeArray saRet;
   DWORD numElements[] = { 10, 10 }; // 10x10

   // Create the 2 dimensional safe-array of type VT_R8 with size 10x10
   saRet.Create(VT_R8, 2, numElements);

   // Initialize safearray  with values...
   long index[2];
   for (index[0] = 0; index[0] < 10; index[0]++)
   {
      for (index[1] = 0; index[1] < 10; index[1]++)
      {
         double val = index[0] + index[1] * 10;
         //populate the safearray elements with double values
         saRet.PutElement(index, &val);
      }
   }
   // Return the safe-array encapsulated in a VARIANT...
   return saRet.Detach();
}

COleSafeArray::Redim

Changes the least significant (rightmost) bound of a safe array.

void Redim(SAFEARRAYBOUND* psaboundNew);

Parameters

psaboundNew
Pointer to a new safe array bound structure containing the new array bound. Only the least significant dimension of an array may be changed.

Remarks

On error, the function throws a COleException.

COleSafeArray::ResizeOneDim

Changes the number of elements in a one-dimensional COleSafeArray object.

void ResizeOneDim(DWORD dwElements);

Parameters

dwElements
Number of elements in the one-dimensional safe array.

Remarks

On error, the function throws a COleException.

Example

See the example for COleSafeArray::CreateOneDim.

COleSafeArray::UnaccessData

Decrements the lock count of an array and invalidates the pointer retrieved by AccessData.

void UnaccessData();

Remarks

On error, the function throws a COleException.

Example

See the example for COleSafeArray::AccessData.

COleSafeArray::Unlock

Decrements the lock count of an array so it can be freed or resized.

void Unlock();

Remarks

This function is called after access to the data in an array is finished. On error, it throws a COleException.

See also

Hierarchy Chart
COleVariant Class
CRecordset Class
CDatabase Class