英文:
How to directly access to what's in VARIANT variables in C++?
问题
我的程序使用外部的ocx库,并通过它接收数据。下面的代码显示了它是如何工作的。
VARIANT varArrItem, varArrData;
ocx_instance.GetItemArr(real, &varArrItem); // 1) 接收数据
long lLBound, lUBound;
VARIANT varItem, varData;
long index[2];
index[0] = 0;
index[1] = 0;
COleSafeArray* pSafeItemArr = (COleSafeArray*)&varArrItem; // 2) 将varArrItem转换为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) 使用GetElement获取其值
strItem = varItem.bstrVal;
arrItem.Add(strItem);
VariantClear(&varItem);
}
该程序的一个重大问题是,这段代码每当有新数据到达时都会运行,而这种情况非常频繁,会消耗大量资源。因此,我想简化代码,只获取varArrItem
的内容,例如作为字符串或字符串数组的结构体数组。
varArrItem.vt
给我8204,它由8192(VT_ARRAY)
和12(VT_VARIANT)
组成。我在这里陷入困境,不知道在此之后该怎么做。如何简单地获取其中的内容?是否可以在不使用COleSafeArray的情况下访问它们?
英文:
My program uses an external ocx library and receives data through it. The code below shows how it works.
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);
}
A big problem of the program is that this code is run whenever new data arrives, which is quite often, and it consumes a lot of resources. So, I'd like to simplify the code and get just contents of varArrItem
, as strings or an array of structs of strings, for example.
varArrItem.vt
gives me 8204 and it's said that it consists of 8192(VT_ARRAY)
and 12(VT_VARIANT)
. I'm stuck here and don't know what to do after this. How can I simply get what's in them? Is it possible to access to them without using COleSafeArray?
答案1
得分: 1
不需要使用 COleSafeArray
,它只是一个方便的包装器。您可以直接从 varArrItem
中提取 SAFEARRAY*
指针,然后直接使用 SafeArray API:SafeArrayGet(L|U)Bound()
、SafeArrayGetElement()
等等。如果性能很重要,可以考虑使用 SafeArrayAccessData()
直接访问 VARIANT[]
数组以及其中的 BSTR
指针。您在处理数据时进行的拷贝操作越少,代码运行速度就越快。这段代码实际上需要进行的唯一数据拷贝是初始 VARIANT
的赋值以及将每个 CString
添加到 CStringArray
中:
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);
}
英文:
You don't NEED to use COleSafeArray
, it is just a wrapper for convenience. You could just extract the SAFEARRAY*
pointer directly from varArrItem
and then use the SafeArray APIs directly: SafeArrayGet(L|U)Bound()
, SafeArrayGetElement()
, etc, though if performance is important then consider using SafeArrayAccessData()
to access the VARIANT[]
array directly, and thus its BSTR
pointers. The less copying of data you do, the faster the code will run. The only copy of data this code actually needs to make is the assignment of the initial VARIANT
and each CString
you add to the CStringArray
:
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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论