如何遍历SAFEARRAY **?

11
2个回答

24

Safearrays是使用SafeArrayCreateSafeArrayCreateVector创建的,但是由于您询问如何遍历SAFEARRAY,假设您已经有了由其他函数返回的SAFEARRAY。一种方法是使用SafeArrayGetElement API,如果您有多维SAFEARRAYs,这特别方便,因为它允许更容易地指定索引。

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

假设它是一个long的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);

7
如果你不是该数组的所有者,那么SafeArrayDestroy()函数不应该出现在这段代码中。不要销毁它。 - Hans Passant
1
“get them from somewhere” 意味着典型场景,即某个方法返回 SAFEARRAY 作为 [out] 参数,此时客户端负责清理工作,但这点可能不是很明显。我已经编辑了回答。 - Zdeslav Vojkovic
当我有两个维度时,如何访问Safearray? - savi
1
@Zdeslav:Hans Passant是正确的。想象一下,你的函数的调用者之后将相同的SAFEARRAY传递给另一个函数以对数据进行其他操作!代码将失败,因为函数破坏了作为输入参数传递的数据,这是设计错误。应该是调用者的函数负责销毁SAFEARRAY。如果每个函数仅破坏自己的数据,您永远不会遇到问题。将其视为写在石头上的设计规则。如果SAFEARRAY来自Windows API,则可以将其存储在COleSafeArray中,以便析构函数销毁它。 - Elmue

4

你最后的链接已经失效了。 - Simon Mourier
@SimonMourier:谢谢,我已经用缓存链接替换了。我不确定原始内容是永久还是暂时不可用。 - Roman R.
1
我在这里找到了它:https://blogs.msmvps.com/gdicanio/2011/02/04/simplifying-safearray-programming-with-ccomsafearray/,使用谷歌帮助。 - Simon Mourier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接