See the question and my original answer on StackOverflow

Your array is not an array of VARIANT but an array of IUnknown* (a call to SafeArrayGetVartype would have told you that). You'll have to change your code for something like this:

SAFEARRAY *psa = pDB->GetData();
if (psa)
{
    SafeArrayLock(psa);
    LONG lb;
    LONG ub;
    SafeArrayGetLBound(psa, 1, &lb);
    SafeArrayGetUBound(psa, 1, &ub);
    for (int i = lb; i <= ub; i++)
    {
        _DownloadPtr download(((IUnknown**)psa->pvData)[i]);
        wprintf(L"%s\n", (LPWSTR)download->GetTarget());
    }
    SafeArrayUnlock(psa);
}

Note it means your Download class must also be marked as [ComVisible(true)], and the fields be transformed into public properties. Because you need an IUnknown interface in this example (to see methods such as GetTarget() automatically added to the generated C++ code), I also suggest you add a [ClassInterface(ClassInterfaceType.AutoDual)] attribute to it.

If you do want array of VARIANTs (why would you?), then you'll have to use object[] instead of typed objects.arrays.