遍历 BSTR 的 VARIANT/SAFEARRAY 以在 C++ 中分配值并打印到控制台
Posted
技术标签:
【中文标题】遍历 BSTR 的 VARIANT/SAFEARRAY 以在 C++ 中分配值并打印到控制台【英文标题】:Iterating through a VARIANT/SAFEARRAY of BSTR to Assign Values and Print to Console in C++ 【发布时间】:2014-07-28 21:08:48 【问题描述】:我正在尝试用值“test”填充 BSTR 类型的 10 个索引的 SAFEARRAY,并在分配 SAFEARRAY 的每个索引以验证正确性后打印出来以控制它的值。我运行调试器并为前 5 个索引获得了以下这些值(我的 SAFEARRAY 称为 sa)。不知何故,我错误地迭代了 SAFEARRAY 或使用了错误的类型,每个索引都应该是“测试”。关于我做错了什么有什么建议吗?
sa[0] = "test"
sa[1] = "est"
sa[2] = "st"
sa[3] = "t"
sa[4] = ""
....
#include <iostream>
#include <string>
#include <Windows.h>
#include <atlbase.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
using namespace std;
void fillVariant(VARIANT& varIn, BSTR &srcArray);
int main()
BSTR *theArray = new BSTR[10];
for(int i = 0 ; i < 10; i++)
theArray[i] = SysAllocString(L"test");
VARIANT variantArray;
fillVariant(variantArray, *theArray);
return 0;
void fillVariant(VARIANT& varIn, BSTR &srcArray)
VARIANT *variantArray = &varIn;
VariantInit(variantArray);
variantArray->vt = VT_ARRAY|VT_BSTR;
SAFEARRAY* sa;
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 0;
aDim[0].cElements = 10;
sa = SafeArrayCreate(VT_BSTR, 1, aDim);
BSTR* dwArray = NULL;
SafeArrayAccessData(sa, (void**)&dwArray);
for(int i = 0; i < 10; i++)
dwArray[i] = &srcArray[i];
BSTR tmp = (BSTR) dwArray[i];
std::wstring ws(tmp);
//std::wstring ws(*dwArray[i], SysStringLen(dwArray[i]));
std::wcout << ws << endl;
SafeArrayUnaccessData(sa);
variantArray->parray = sa;
【问题讨论】:
必须使用原始SAFEARRAY
吗? CComSafeArray 提供了一个更易于使用的包装器。
您应该使用 SafeArrayPutElement 将元素放入 SAFEARRAY
BSTR *theArray = new BSTR[10];
可以简化为BSTR theArray[10];
【参考方案1】:
您没有正确填写VARIANT
。试试这个:
#include <iostream>
#include <string>
#include <Windows.h>
#include <atlbase.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
using namespace std;
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen);
int main()
BSTR *theArray = new BSTR[10];
for(int i = 0 ; i < 10; i++)
theArray[i] = SysAllocString(L"test");
VARIANT variantArray;
fillVariant(variantArray, theArray, 10);
// don't forget to free memory when done!
// note: the VARIANT owns the BSTRs, so DON'T free them!
VariantClear(&variantArray);
delete[] theArray;
return 0;
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen)
VARIANT *variantArray = &varIn;
VariantInit(variantArray);
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 0;
aDim[0].cElements = srcArrayLen;
SAFEARRAY* sa = SafeArrayCreate(VT_BSTR, 1, aDim);
if (sa)
BSTR* dwArray = NULL;
SafeArrayAccessData(sa, (void**)&dwArray);
for(int i = 0; i < srcArrayLen; i++)
// note: passing ownership, NOT making a copy
dwArray[i] = srcArray[i];
//std::wstring ws(dwArray[i], SysStringLen(dwArray[i]));
std::wcout << dwArray[i] << endl;
SafeArrayUnaccessData(sa);
variantArray->vt = VT_ARRAY|VT_BSTR;
variantArray->parray = sa;
或者:
#include <iostream>
#include <string>
#include <Windows.h>
#include <atlbase.h>
#include <comutil.h>
#include <string.h>
#include <stdio.h>
using namespace std;
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen);
int main()
BSTR *theArray = new BSTR[10];
for(int i = 0 ; i < 10; i++)
theArray[i] = SysAllocString(L"test");
VARIANT variantArray;
fillVariant(variantArray, theArray, 10);
// don't forget to free memory when done!
VariantClear(&variantArray);
// note: the VARIANT DOES NOT own the BSTRs, so DO free them!
for(int i = 0 ; i < 10; i++)
SysFreeString(theArray[i]);
delete[] theArray;
return 0;
void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen)
VARIANT *variantArray = &varIn;
VariantInit(variantArray);
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound = 0;
aDim[0].cElements = srcArrayLen;
SAFEARRAY* sa = SafeArrayCreate(VT_BSTR, 1, aDim);
if (sa)
for(LONG i = 0; i < srcArrayLen; i++)
// note: makes a copy, DOES NOT pass ownership!
SafeArrayPutElement(sa, &i, srcArray[i]);
//std::wstring ws(srcArray[i], SysStringLen(srcArray[i]));
std::wcout << srcArray[i] << endl;
variantArray->vt = VT_ARRAY|VT_BSTR;
variantArray->parray = sa;
【讨论】:
【参考方案2】:&srcArray[i]
不会做你认为的那样。 srcArray
是单个 BSTR
,它是 WCHAR*
的 typedef。它不是BSTR
s 的数组。 srcArray[i]
指的是theArray[0]
中的第i
个字符,&srcArray[i]
是该字符的地址。这就是你得到“test”、“est”等的方式。
让fillVariant
将BSTR*
作为其第二个参数,并传递theArray
,而不是*theArray
。
在不相关的注释中,您的程序泄漏了一堆BSTR
s 和一个SAFEARRAY
。
【讨论】:
以上是关于遍历 BSTR 的 VARIANT/SAFEARRAY 以在 C++ 中分配值并打印到控制台的主要内容,如果未能解决你的问题,请参考以下文章