Library Zone Articles
External Articles
Byte Size

Discovery Zone Catalogue
Diary
Links
Bookstore
Interactive Zone Ask the Gurus
Discussion Groups
Newsletters
Feedback
Etc Cartoons
Humour
COMpetition
Advertising
Site Builder ASP Web Ring ASP Web Ring

Click here
The Developer's Resource & Community Site
COM XML ASP Java & Misc. NEW: VS.NET
International This Week Forums Author Central Find a Job

SafeArrays - For the Beginner

Introduction

The following article is meant as a primer to Safe Arrays. This can be used by any beginner to Safe Arrays. It consists of a documentation of the most frequently used functions, their explanations followed by examples. For more details about the other functions and a detailed technical explanation about introduction to safe arrays please refer to the MSDN documentation.

A Safe Array is defined as an array that contains information about the number of dimensions and the bounds of its dimensions. This is one of the most commonly used COM data types. We will see some of the most commonly used SafeArray methods now.

Fundamental Safe Array Methods: SafeArrayMethod - SafeArrayCreate

Any array needs to be created and allocated memory before it is used. This function creates a new array descriptor, allocates and initializes the data for the array, and returns a pointer to the new array descriptor. The function signature is as follows,


SAFEARRAY SafeArrayCreate( VARTYPE vt, unsigned int cDims, SAFEARRRAYBOUND FAR* rgsabound );

Parameters

vt

The base type of the array (the VARTYPE of each element of the array). This indicates the type of data that can be stored in the array. Hence if you specify VT_BSTR it means that the array contains members of type BSTR's. If you are unsure about the data type that can be stored you can make it VT_VARIANT. 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.

cDims

Number of dimensions in the array. The number cannot be changed after the array is created. For example, a 1D array would have the value of cDims as 1 and a 2d array would have the value of cDims as 2 and so on.

rgsabound

Pointer to a vector of bounds (one for each dimension) to allocate for the array. This is a SAFEARRAYBOUND structure. The structure is defined as follows.


typedef struct tagSAFEARRAYBOUND {
    unsigned long cElements;
    long lLbound;
} SAFEARRAYBOUND;

lLbound - Denotes the lower bound of the particular dimension and
cElements - Denotes the number of elements in that dimension

1. Example for SAFEARRAYBOUND

To declare a 1D safearray which has 5 elements and starts from 0, the SAFEARRAYBOUND structure has to be initialized as follows.


SAFEARRAYBOUND rgsabound[1];  //Denotes number of dimensions
rgsabound[0]. lLbound =0;
rgsabound[0]. CElements=5;

To declare a 2D safearray which has 5 elements in the first dimension and starts from 0 and 10 elements in the second dimension starting from 0, the SAFEARRAYBOUND structure has to be initialized as follows.


SAFEARRAYBOUND rgsabound2D[2];  //Denotes number of dimensions
rgsabound2D[0]. lLbound =0;
rgsabound2D[0]. CElements=5;
rgsabound2D[1]. lLbound =0;
rgsabound2D[1]. CElements=10;

2. Example for SafeArrayCreate using the SAFEARRAYBOUND (Example 1) created above


/* 
Create a 1D SafeArray of variants with the SAFEARRAYBOUND from the previous example 
*/
SafeArrayCreate(VT_VARIANT, 1, rgsabound)

SafeArrayMethod - SafeArrayCreateVector

An easier method to construct a 1D safearray whose lower bound is always zero is this method wherein there is no initialization of the SAFEARRAYBOUND structure etc. The function signature is as follows,


SAFEARRAY SafeArrayCreateVector( 
  VARTYPE  vt,             
  long  lLbound,           
  unsigned int  cElements  
);

Creates a one-dimensional array whose lower bound is always zero.

Parameters

vt

The base type of the array (the VARTYPE of each element of the array). This indicates the type of data that can be stored in the array. Hence if you specify VT_BSTR it means that the array contains members of type BSTR's. If you are unsure about the data type that can be stored you can make it VT_VARIANT. 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.

lLbound

The lower bound for the array. Can be negative.

cElements

The number of elements in the array.

Return Value

Points to the array descriptor, or Null if the array could not be created.

3. Example for SafeArrayCreateVector


// Creates a safearray of variants containing 3 elements with the lower bound starting at 0 

SAFEARRAY *psa;
long NoOfElements=3;
psa=SafeArrayCreateVector(VT_VARIANT, 0, NoOfElements);

SafeArrayMethod - SafeArrayGetDim

This method is used to find out the number of dimensions with which the safe array has been created. The function signature is as follows,


UINT SafeArrayGetDim( SAFEARRAY FAR* psa ); 

Parameter

psa

Pointer to an array descriptor created by SafeArrayCreate.

Return Value

Returns the number of dimensions in the array.

4. Example for SafeArrayGetDim


// Try getting the dimension for the safearray created in Example 3

SafeArrayMethod - SafeArrayGetElement

This method is used to retrieve a single element from an already populated safe array. The function signature is as follows,


HRESULT SafeArrayGetElement( SAFEARRAY FAR* psa, long FAR* rgIndices, void FAR* pv ); 

Parameters

psa

Pointer to an array descriptor created by SafeArrayCreate.

rgIndices

Pointer to a vector of indexes for each dimension of the array. The right-most (least significant) dimension is rgIndices[0]. The left-most dimension is stored at rgIndices[psa->cDims - 1]. Look at the examples given below for accessing the elements of a 1D array and a 2D array.

pv

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

5. Example for a 1D SafeArrayGetElement


long lbound;
hr=SafeArrayGetLBound(psa, 1, &lbound); //Get the lower bound of the safearray
long ubound;
hr=SafeArrayGetUBound(psa, 1, &ubound); // Get the upper bound of the safearray
//Navigate through the safe array
for(;lbound<=ubound;lbound++)
{
	CComVariant val;
	SafeArrayGetElement(psa, &lbound, (void *) & val);
	::MessageBox(0,OLE2T(val.bstrVal), "Value",0);	
}

6. Example for a 2D SafeArrayGetElement


long aiIndex[2];	//Declare array equal to the number of bounds
psa=SafeArrayCreate(VT_VARIANT, 2, rgsabound); //Create the safe array
/*
aiIndex[0] - Represents the starting index of the row
aiIndex[1] - Represents the starting index of the column
Navigate through the safe array by getting the elements
of each row and then moving forward to the next row
always taking care to check that aiIndex[0] is less
than the maximum row bound and aiIndex[1] is less than
the maximum column bound
*/
for(aiIndex[0] = 0; aiIndex[0] %lt; 2; aiIndex[0]++)
{
	for(aiIndex[1] = 0; aiIndex[1] < 2; aiIndex[1]++)
	{
		CComVariant val;
		SafeArrayGetElement(psa, aiIndex, (void *) & val);
		::MessageBox(0,OLE2T(val.bstrVal), "Value",0);	
	}
}

UINT dim;
dim=SafeArrayGetDim(psa); // Will return 1

SafeArrayMethod - SafeArrayPutElement

This method is used to assign a single element to an already populated safe array. The function signature is as follows,


HRESULT SafeArrayPutElement( SAFEARRAY FAR* psa, long FAR* rgIndices, void FAR* pv );

Parameters

psa

Pointer to an array descriptor created by SafeArrayCreate.

rgIndices

Pointer to a vector of indexes for each dimension of the array. The right-most (least significant) dimension is rgIndices[0]. The left-most dimension is stored at rgIndices[psa->cDims - 1]. Look at the examples given below for putting elements into a 1D array and a 2D array.

pv

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

7. Example for a 1D SafeArrayPutElement


long count=0;
CComVariant name="Satyam";
hr=SafeArrayPutElement(psa, &count, (void *) &name);

//Always increment the count
count++;
name="Computers";
hr=SafeArrayPutElement(psa, &count, (void *) &name);

8. Example for a 2D SafeArrayPutElement


USES_CONVERSION;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[2]; 
rgsabound[0].cElements = 2;
rgsabound[0].lLbound = 0;
rgsabound[1].cElements = 2;
rgsabound[1].lLbound = 0;
psa=SafeArrayCreate(VT_VARIANT, 2, rgsabound);  //Create a 2D safe array
long aiIndex[2];	

/*
aiIndex[0] - Represents the starting index of the row
aiIndex[1] - Represents the starting index of the column
Navigate through the safe array by putting the elements of
each row and then moving forward to the next row always
taking care to check that aiIndex[0] is less than the
maximum row bound and aiIndex[1] is less than the maximum column bound
*/
	
for(aiIndex[0] = 0; aiIndex[0] < 2; aiIndex[0]++)
{
	for(aiIndex[1] = 0; aiIndex[1] < 2; aiIndex[1]++)
	{
		CComVariant var="Satyam";
		hr=SafeArrayPutElement(psa,aiIndex,& var);
	}
}

Summary

The article covered some of the main methods of Safe Arrays and provided comprehensive examples of how to put them to use. Some of the confusion about safe arrays results from a lack of clear understanding of how to use them in the correct situations. I hope this article will serve as a ready reckoner for people who are new to this topic or for those who are well versed with this topic but may need some kind of an online reference.

For further information refer to the source code of published articles


Further reading

About the author

The author is a professional developer with around 2 years of development experience. His areas of interest include AS/400, Lotus Domino, Java, ASP, HTML, JavaScript, VBScript, C++ and COM.

Please visit this author in Author Central.

Rate and Review this article

To review this article and rate it out of 5, please send an email to [email protected], using the article heading as the sublect line of your message.


Girls Geeks

Contribute to IDR:

To contribute an article to IDR, a click here.

To contact us at IDevResource.com, use our feedback form, or email us.

To comment on the site contact our webmaster.

Promoted by CyberSavvy UK - website promotion experts

All content © Copyright 2000 IDevResource.com, Disclaimer notice

Join the Developers Webring

Java COM integration

Visit the IDR Forums

WTL Introduction