65.9K
CodeProject 正在变化。 阅读更多。
Home

使用宏简化您的 Safearray 循环

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (3投票s)

2001 年 7 月 31 日

3分钟阅读

viewsIcon

132873

downloadIcon

1614

一篇关于如何简化 safearray 使用的文章

本文的目的是展示如何在 VC++ 中简化你的 safearray 编程,以及如何使代码更具可读性。本文将简要定义 safearray,并介绍一组新的宏以及如何使用它们。

Safearrays

什么是 Safearrays?正如其名称所示,它是一种安全的数组数据类型,这意味着它会跟踪其限制和边界,因此限制在这些边界内的访问。Safearrays 用于传递封装在 Variants 中的数组(它们的基类型是 VT_? | VT_ARRAY),例如在 COM 对象之间。

Safearrays 绝对不能与 C/C++ 数组混淆,C/C++ 数组不 "安全"。在使用 Visual Basic COM 对象和 Visual Basic 数组时,你唯一的选择是学习如何使用 Safearrays,MSDN 是一个关于此主题的良好信息来源(或者可能是未来更详尽的文章 :-)。

如何循环遍历 Safearray

那些熟悉 Safearrays 的人知道,遍历 Safearray 需要大量的代码行。下面的示例 [示例 1] 显示了在遍历包含 Variants 的 Safearray 时代码的样子。

// Safearray loop [sample 1]
// this example assumes that you have a Safearray in a VARIANT (vArray) 
// with the type VT_ARRAY | VT_BSTR

// variables
LONG lstart, lend;
LONG idx = -1;
LONG nPos;
HRESULT hr;
BSTR* pbstr;

// assign the Safearray
SAFEARRAY *sa = V_ARRAY( &vArray ); 

// Get the lower and upper bound
hr = SafeArrayGetLBound( sa, 1, &lstart );
if(FAILED(hr)) return hr;
hr = SafeArrayGetUBound( sa, 1, &lend );
if(FAILED(hr)) return hr;

// loop
hr = SafeArrayAccessData(sa,(void HUGEP**)&pbstr);
if(SUCCEEDED(hr))
{
	for(idx=lstart; idx <= lend; idx++)
	{		
		CComBSTR s;
		s = pbstr[idx];
		// s now contains the item at position idx in the array
		
		// ...		
	}
	hr = SafeArrayUnaccessData(sa);	
	if(FAILED(hr)) return hr;
}	
else
	return hr
// (23 lines of code)

注意代码量,想象一下,如果我们能将其减少到 8 行,并想想你的代码将更容易解释,也更容易让其他人理解。

提示! 还要注意我们如何使用 SafeArrayAccessData 来访问循环中的数据,而不是使用 SafeArrayGetElement 来提高性能。

如何使用宏循环 Safearray

为了使我的代码更容易阅读并使编程更快,我创建了一组宏来使 Safearray 编程更容易。让我们看看上面相同的示例 [示例 1],使用宏 [示例 2]。

// Safearray loop [sample 2]
// this example assumes that you have a Safearray in a VARIANT (vArray) with 
// the type VT_ARRAY | VT_BSTR

#include "safearray_macro.h"

// variables
BSTR* pbstr;

// loop
BEGIN_SA_V(vArray,pbstr)
    BEGIN_SA_LOOP()
        CComBSTR s;
        s = pbstr[INDEX_SA];
        // s now contains the item at the current position in the array
        // ...        
    END_SA_LOOP();
END_SA();
        
// (8 lines of code)
Easy, huh? Just an include file and a new set of macros...

Let's see what the different macros are doing...

宏定义

BEGIN_SA_V(vArray, pvar)
启动宏部分并定义所需的局部变量。vArray 是一个包含 Safearray 的 Variant,pvar 是在循环中用于数组中每个项的变量。

BEGIN_SA(sa, pvar)
启动宏部分并定义所需的局部变量。sa 是一个 Safearray,pvar 是在循环中用于数组中每个项的变量。

END_SA()
结束宏部分。

BEGIN_SA_LOOP()
启动循环。INDEX_SA 是迭代器变量,你可以使用 pvar[INDEX_SA] 访问当前项。

END_SA_LOOP()
循环的结尾。

INDEX_SA
是循环内的迭代器变量(类型为 LONG)。

BREAK_SA()
可以在实际循环中使用它来中断循环,只要它没有出现在嵌套的 for 循环中。

QUIT_SA()
如果计划在循环内退出方法,则应使用此宏以确保 Safearray 已关闭。

SAFEARRAY_SA
如果想直接访问 SAFEARRAY 对象,则可以使用此宏。当 Safearray 存在于 Variant 中时很有用。

演示

要测试宏,请测试包含的 VC++ 和 VB 项目,它们说明了 BEGIN_SA_VBEGIN_SA 宏。

源和用法

只需包含 #include "safearray_macro.h",将文件包含在你的代码中并开始使用它。如果对其进行任何扩展/修改,请通知我!

玩得开心...
/WW

© . All rights reserved.