如何在 C++ 中直接访问 VARIANT 变量中的内容?

How to directly access to what's in VARIANT variables in C++?

我的程序使用外部ocx库并通过它接收数据。下面的代码显示了它是如何工作的。

    VARIANT    varArrItem, varArrData;

    ocx_instance.GetItemArr(real, &varArrItem);      // the library provides GetItemArr
                                                     // 1) receives data 
    long lLBound, lUBound;
    VARIANT varItem, varData;

    long index[2];
    index[0] = 0;
    index[1] = 0;

    COleSafeArray* pSafeItemArr = (COleSafeArray*)&varArrItem;    // 2) casts varArrItem to COleSafeArray
    CString strItem;
    CStringArray arrItem;

    pSafeItemArr->GetLBound(1, &lLBound);
    pSafeItemArr->GetUBound(1, &lUBound);

    int nItemCnt = (lUBound - lLBound + 1);
    for (int i = 0; i < nItemCnt; i++)
    {
        index[0] = i;
        VariantInit(&varItem);

        pSafeItemArr->GetElement(index, (void *)&varItem);    // 3) gets its values using GetElement
        strItem = varItem.bstrVal;
        arrItem.Add(strItem);

        VariantClear(&varItem);
    }

该程序的一个大问题是,每当有新数据到达时,这段代码就会运行,这种情况非常频繁,并且会消耗大量资源。因此,我想简化代码并仅获取 varArrItem 的内容,例如字符串或字符串结构数组。

varArrItem.vt给我8204,据说它由8192(VT_ARRAY)12(VT_VARIANT)组成。我被困在这里,不知道之后该怎么办。我怎样才能简单地得到其中的内容?是否可以在不使用 COleSafeArray 的情况下访问它们?

您不需要使用 COleSafeArray,它只是为了方便起见的包装器。您可以直接从 varArrItem 中提取 SAFEARRAY* 指针,然后直接使用 SafeArray API:SafeArrayGet(L|U)Bound()SafeArrayGetElement() 等,但如果性能很重要,请考虑使用 SafeArrayAccessData() 直接访问 VARIANT[] 数组,从而访问它的 BSTR 指针。您复制的数据越少,代码就会越快运行。此代码实际需要制作的唯一数据副本是初始 VARIANT 的赋值以及您添加到 CStringArray:

的每个 CString
VARIANT varArray;
ocx_instance.GetItemArr(real, &varArray);

LPSAFEARRAY psa = varArrar.parray;

LONG lLBound, lUBound;
SafeArrayGetLBound(psa, 1, &lLBound);
SafeArrayGetUBound(psa, 1, &lUBound); 

CStringArray arrItem;

VARIANT *varArrayData;
if (SUCCEEDED(SafeArrayAccessData(psa, (void**) &varArrayData)))
{
    int nItemCnt = (lUBound - lLBound + 1);

    for (int i = 0; i < nItemCnt; i++)
    {
        CString strItem = varArrayData[i].bstrVal;
        arrItem.Add(strItem);
    }

    SafeArrayUnaccessData(psa);
}