For COM developers targeting Visual Basic and Java clients, the only way to effectively transfer arrays between objects and clients is to use SAFEARRAYs. SAFEARRAYs are self-describing, self-bounded arrays. Unfortunately, using SAFEARRAYs requires you to work with a complex API of C functions.
COtlSafeArray is useful for creating and accessing multiple-dimension SAFEARRAYs. The syntax for using COtlSafeArray is generally simpler than working with the SAFEARRAY API. The COtlSafeArray class supports constructing empty arrays and adding elements as well as copying arrays from existing arrays. Here is a code example for a method using an array of BSTRs:
#include "otlsafearray.h"
using namespace StingrayOTL;
void UseSafeArray()
OtlSABSTR* posaBSTR; // OTL predefined type…
long rgnBounds[1];
rgnBounds[0] = 10;
m_posaBSTR = new OtlSABSTR;
SomeFunctionThatGeneratesASafeArray(VT_BSTR, 1,
for(long l = 0; l < posaBSTR->GetSingleDimSize(); l++)
BSTR bstr;
posaBSTR->GetElement(l, &bstr);
CString str(bstr);
// test the [] operator
BSTR bstrTemp = ((*posaBSTR)[l]);
CString strTemp(bstrTemp);
ASSERT(strTemp == str);
// do something with the string...
if(posaBSTR) {
delete posaBSTR;
COtlSimpleSafeArray is used for creating and accessing single dimension SAFEARRAYs. The class allows a SAFEARRAY to be used like a normal C style array. This is especially useful for creating [out] SAFEARRAY or VARIANT array parameters. COtlSimpleSafeArray is templated on the type of element contained in the array. There are several constructors for creation based on an existing VARIANT or SAFEARRAY, or an empty array. You can also construct the array with an [out] SAFEARRAY** or VARIANT* parameter, which automatically receives the array in the COtlSimpleSafeArray destructor. The following code is of a method in a server that creates and returns a SAFEARRAY of BSTRs:
STDMETHODIMP CSimpleServer::GetNames(VARIANT *pNames)
// create a new SafeArray with 4 elements.
// passing the [out] pNames parameter allows auto assignment on
// destruction
COtlSimpleSafeArray<BSTR> array(pNames, VT_BSTR, 4);
array[0] = ::SysAllocString(L"Don Box");
array[1] = ::SysAllocString(L"Tim Ewald");
array[2] = ::SysAllocString(L"Chris Sells");
array[3] = ::SysAllocString(L"George Shepherd");
return S_OK;