![]() | 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.
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; }
When a client application calls a driver that returns a SAFEARRAY, the client must free the SAFEARRAY that is allocated by the driver.
// MyClient.cpp 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... }