在c++中迭代BSTR的VARIANT/SAFEARRAY来赋值并打印到控制台

Iterating through a VARIANT/SAFEARRAY of BSTR to Assign Values and Print to Console in C++

本文关键字:赋值 打印 控制台 SAFEARRAY c++ 迭代 BSTR VARIANT      更新时间:2023-10-16

我试图用值"test"填充10个BSTR类型索引的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;
}

您没有正确填写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;
    }
}

&srcArray[i]并不像你想象的那样。srcArray是单个BSTR,它是WCHAR*的类型定义。它是不是BSTR s数组。srcArray[i]theArray[0]中的第i个字符,&srcArray[i]是该字符的地址。这就是为什么会有"test", "est"等等。

fillVariantBSTR*作为第二个参数,传递theArray,而不是*theArray

不相关的是,你的程序泄漏了一堆BSTR s和一个SAFEARRAY