Why is my variant showing as VT_EMPTY despite containing a safearray

222 Views Asked by At

I am trying to return an array which is a portion of a vector to VBA. The vector is just an array of data from a test file stored as an std::string. I would like to pass a Row variable to the DLL and have this return the given data from that line down to that line + 1000. The issue is that the return variant is just showing as VT_EMPTY in VBA. Can anyone help, I am quite new to C++ in general, and haven't got much COM experience.

LONG __stdcall BDH::GetRange(const uint32_t& Row, const uint32_t& Column, VARIANT* pDest)
{
    // Validate row
    if (!(Row - 1 > 0))
        return -1;
    
    // Validate column
    if (!(Column - 1 > 0))
        return -1;

    // Check row isn't biggest than the last index
    if (Row - 1 > SourceData.size())
        return -1;

    // Check column isn't biggest than the last index of the first element
    if (Column - 1 > SourceData[0].size())
        return -1;

    HRESULT hr = CoInitialize(NULL);

    // Initialise the return variant and set the vartype to variant array
    VariantInit(pDest);
    pDest->vt = VT_VARIANT | VT_ARRAY;

    // Create safearray and bound object
    SAFEARRAYBOUND Bound[2];

    Bound[0].lLbound = 1; // Array starting at 1 (VBA style)

    // Decide whether the size should be 1000 or the difference between row and size
    if ((SourceData.size() - Row) < 1000)
        Bound[0].cElements = SourceData.size() - Row;
    else
        Bound[0].cElements = 1000;

    Bound[1].lLbound = 1; // Start at 1
    Bound[1].cElements = SourceData[0].size(); // Set the second dimension size

    pDest->parray = SafeArrayCreate(VT_VARIANT, 2, Bound); // Create the safearray within the variant 

    // Iterators and array indices data
    uint32_t i, j;
    LONG Indices[2];

    for (uint32_t i = Row - 1; i < Row - 1 + 1000; i++)
        for (uint32_t j = 0; j < SourceData[i].size() - 1; j++)
        {
            // Set the index
            Indices[0] = i;
            Indices[1] = j;

            // Create the variant
            VARIANT Element;
            VariantInit(&Element);
            Element.vt = VT_BSTR;
            
            // Set the string value (use SysAllocStringByteLen to reduce space - string is ANSI)
            Element.bstrVal = SysAllocStringByteLen(SourceData[i][j].c_str(), SourceData[i][j].size());

            // Add the element to the safearray
            SafeArrayPutElement(pDest->parray, Indices, &Element);
        }

    return 0;
}

EDIT: Example of wrapper for this function

__declspec(dllexport) void __stdcall ExampleWrapper(LONG x, LONG y, VARIANT* pDest)
{
    BDH bdh;
    bdh.GetRange((uint32_t)x, (uint32_t)y, pDest);
}
0

There are 0 best solutions below