【问题标题】:How to iterate through SAFEARRAY **如何遍历 SAFEARRAY **
【发布时间】:2018-10-14 07:16:11
【问题描述】:

如何遍历 C++ 安全数组指针并访问其元素。

我尝试复制 Lim Bio Liong 发布的解决方案 http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/022dba14-9abf-4872-9f43-f4fc05bd2602 但最奇怪的是,IDL 方法签名竟然是

HRESULT __stdcall GetTestStructArray([out] SAFEARRAY ** test_struct_array);

而不是

HRESULT __stdcall GetTestStructArray([out] SAFEARRAY(TestStruct)* test_struct_array);

有什么想法吗?

提前致谢

【问题讨论】:

    标签: c++ com safearray


    【解决方案1】:

    Safearrays 是使用SafeArrayCreateSafeArrayCreateVector 创建的,但是当您询问迭代 SAFEARRAY 时,假设您已经有一个由其他函数返回的 SAFEARRAY。一种方法是使用SafeArrayGetElement API,如果您有多维 SAFEARRAY,这将特别方便,因为它允许 IMO 更轻松地指定索引。

    但是,对于向量(一维 SAFEARRAY),直接访问数据并迭代值会更快。这是一个例子:

    假设它是longs 的 SAFEARRAY,即。 VT_I4

    // get them from somewhere. (I will assume that this is done 
    // in a way that you are now responsible to free the memory)
    SAFEARRAY* saValues = ... 
    LONG* pVals;
    HRESULT hr = SafeArrayAccessData(saValues, (void**)&pVals); // direct access to SA memory
    if (SUCCEEDED(hr))
    {
      long lowerBound, upperBound;  // get array bounds
      SafeArrayGetLBound(saValues, 1 , &lowerBound);
      SafeArrayGetUBound(saValues, 1, &upperBound);
    
      long cnt_elements = upperBound - lowerBound + 1; 
      for (int i = 0; i < cnt_elements; ++i)  // iterate through returned values
      {                              
        LONG lVal = pVals[i];   
        std::cout << "element " << i << ": value = " << lVal << std::endl;
      }       
      SafeArrayUnaccessData(saValues);
    }
    SafeArrayDestroy(saValues);
    

    【讨论】:

    • SafeArrayDestroy() 不属于此代码。如果您不拥有该数组,请不要销毁它。
    • get them from somewhere 旨在表示一个典型的场景,即有一个方法返回一个 SAFEARRAY 作为[out] 参数,在这种情况下,客户端负责清理,但这可能并不明显。我已经编辑了答案
    • 当我有 2 个维度时如何访问 Safearray?
    • @Zdeslav:Hans Passant 是对的。想象一下,您的函数的调用者随后将相同的 SAFEARRAY 传递给另一个函数以对数据执行其他操作!代码将失败,因为函数破坏作为输入参数传递的数据是设计错误。关心破坏 SAFEARRAY 的一定是你的函数的调用者。如果每个函数只销毁它自己的数据,你就永远不会遇到问题。将此作为一成不变的设计规则。如果 SAFEARRAY 来自 Windows API,您可以将其存储在 COleSafeArray 中,以便析构函数将其销毁。
    【解决方案2】:

    MSDN SafeArrayGetElement function 为您提供了使用 SafeArrayGetElement 获取单个对象到数组的代码 sn-p。

    SAFEARRAY structureSafeArray* 函数解释了可用的 API。

    在 ATL/MFC 项目中,您可能希望使用包装类,例如CComSafeArray 让事情变得更简单和容易。请参阅Simplifying SAFEARRAY programming with CComSafeArray

    【讨论】:

    • 您的最后一个链接已损坏。
    • @SimonMourier:谢谢,我用缓存链接替换了,我不确定原始内容是永久还是暂时不可用。
    • 我在这里找到了它,如果:blogs.msmvps.com/gdicanio/2011/02/04/… 有谷歌帮助
    猜你喜欢
    • 2014-05-14
    • 2012-08-03
    • 1970-01-01
    • 2011-04-09
    • 2010-12-18
    • 2017-01-10
    • 2011-12-21
    • 2012-02-27
    • 2016-11-23
    相关资源
    最近更新 更多