SAFEARRAY Basics
This topic describes common usage of the SAFEARRAY data type. It is generally easier to use CComSafeArray rather than using SAFEARRAY directly. For more information on the CComSafeArray, see CComSafeArray Basics.
Returning a SAFEARRAY
Section titled “Returning a SAFEARRAY”When implementing a method that should return a SAFEARRAY, either as [out, retval], [in, out] or [out], the SAFEARRAY should be allocated by the driver and freed by the client application.
HRESULT Acme4321::Acme4321Table_GetData(SAFEARRAY** val){ HRESULT hr = S_OK;
// Allocate a SAFEARRAY of double with 3 elements SAFEARRAY* psaData = ::SafeArrayCreateVector(VT_R8, 0, 3); if (psaData != NULL) { // Set the value of the 3 elements to 0.0 for (long lIndex = 0; lIndex < 3; lIndex++) { double dVal = 0.0; hr = ::SafeArrayPutElement(psaData, &lIndex, (void*)&dVal); if (FAILED(hr)) break; }
if (SUCCEEDED(hr)) { *val = psaData; } else { ::SafeArrayDestroy(psaData); } } else { hr = ReportError(IDS_E_IVI_OUT_OF_MEMORY); }
return hr;}Receiving a SAFEARRAY
Section titled “Receiving a SAFEARRAY”When a client application calls a driver that returns a SAFEARRAY, the client must free the SAFEARRAY that is allocated by the driver.
void main(){ // Initialize COM, create instance of object...
SAFEARRAY* psaData = NULL; hr = pDriver->GetData(&psaData); if (SUCCEEDED(hr)) { // Determine the size of the array long lLowerBound; hr = ::SafeArrayGetLBound(psaData, 1, &lLowerBound); if (SUCCEEDED(hr)) { long lUpperBound; hr = ::SafeArrayGetUBound(psaData, 1, &lUpperBound); if (SUCCEEDED(hr)) { for (long lIndex = lLowerBound; lIndex <= lUpperBound; lIndex++) { double dVal; hr = ::SafeArrayGetElement(psaData, &lIndex, &dVal); if (SUCCEEDED(hr)) { // Do something with dVal... } } } }
// Free the array ::SafeArrayDestroy(psaData); }
// Release instance of object, terminate COM...}