如何在 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);
}
我的程序使用外部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);
}