SAFEARRAY(安全数组)使用详解
一,何谓SAFEARRAY(安全数组):
winddows操作系统与使用 SAFEARRAY 定义。 下列 SAFEARRAY 结构是 SAFEARRAY 典型、 一般定义:
typedef struct FARSTRUCT tagSAFEARRAY {
unsigned short cDims; // 安全数组的大小
unsigned short fFeatures; //安全数组的标记,取值见下表
#if defined(WIN32) //如果在windows系统上
unsigned long cbElements; //安全数组元素的大小
//不包括安全数组数据的大小
unsigned long cLocks; // 被锁定次数
#else
unsigned short cbElements;
unsigned short cLocks;
unsigned long handle; // 仅用在 Macintosh 系统上
#endif
void HUGEP* pvData; // 数据指针
SAFEARRAYBOUND rgsabound[1]; //安全数组的下界,元素数, 结构见下说明
} SAFEARRAY;
typedef struct tagSAFEARRAYBOUND {
unsigned long cElements;// 元素数
long lLbound;// 数组的下界
} SAFEARRAYBOUND;
fFeatures; //安全数组的标记 | 说明 |
FADF_AUTO 0x0001 | 在栈上创建数组 |
FADF_STATIC 0x0002 | 在堆上创建数组 |
FADF_EMBEDDED 0x0004 | 在结构中创建 |
FADF_FIXEDSIZE 0x0010 | 不能改变数组大小 |
FADF_RECORD 0x0020 | 记录容器 |
FADF_HAVEIID 0x0040 | 有IID 身份标记 数组 |
FADF_HAVEVARTYPE 0x0080 | VT 类型数组 |
FADF_BSTR 0x0100 | BSTR数组 |
FADF_UNKNOWN 0x0200 | IUnknown* 数组 |
FADF_DISPATCH 0x0400 | IDispatch* 数组 |
FADF_VARIANT 0x0800 | VARIANTs数组 |
FADF_RESERVED 0xF0E8 | 余留,将来使用 |
Microsoft Windows 2000 和 WindowsXP 等操作系统系统使用整个 Win32API。 因此, 是运行 Windows 2000 或 WindowsXP, 计算机上之后处理条件指令, Oaidl.h 文件与以下示例代码中可能定义 SAFEARRAY:
typedef struct tagSAFEARRAY {
USHORT cDims;
USHORT fFeatures;
ULONG cbElements;
ULONG cLocks;
PVOID pvData;
SAFEARRAYBOUND rgsabound[ 1 ];
} SAFEARRAY;
Oaidl.h 文件, 中 SAFEARRAYBOUND 是如以下示例代码中定义一个结构:
typedef struct tagSAFEARRAYBOUND {
unsigned long cElements;
long lLbound;
} SAFEARRAYBOUND;
Oaidl.h 文件还包含对于, 可用于访问 SAFEARRAY 函数原型。
二,什么情况下使用
1:在使用vc编写COM组件的时候,需要一次传递很多的数据时,使用SAFEARRAY就会很方便
2:VisualBasic 和 C 之间或在 VisualBasic 和 VisualC++, 之间传递数组或字符串,用 C、 C++ 或 ATL 创建 DLL时用SAFEARRAY。
三,使用实例
1:使用SafeArrayAllocDescriptor在栈上创建一维数组
//创建SAFEARRAY数组,每个元素为long型,该数组是一维数组
long nData[10]={1,2,3,4,5,6,7,8,9,10};
SAFEARRAY* pArray=NULL;
HRESULT hr=SafeArrayAllocDescriptor(1,&pArray);//创建SAFEARRAY结构的对象
pArray->cbElements=sizeof(nData[0]);
pArray->rgsabound[0].cElements=10;
pArray->rgsabound[0].lLbound=0;
pArray->pvData=nData;
pArray->fFeatures=FADF_AUTO|FADF_FIXEDSIZE;//FADF_AUTO指定在栈上分配数据,并且大小不可以改变(固定为10)
//访问SAFEARRAY数组
long* pValue=NULL;
SafeArrayAccessData(pArray,(void**)&pValue);//取得数据存到指针pValue
long Low(0),High(0);
hr=SafeArrayGetLBound(pArray,1,&Low);//维数索引从1开始
hr=SafeArrayGetUBound(pArray,1,&High);//维数索引从1开始
SafeArrayUnaccessData(pArray);
SafeArrayDestroy(pArray);
这种方法在栈上分配数组元素所占的空间,即nData数组所用的空间
2:vc++创建dll, VisualBasic向dll中传数组
Vc++中创建dll工程StdDLL,把下边函数复制到cpp中
long __declspec (dllexport) __stdcall Func2(SAFEARRAY **ppsaMyArray)
{
HRESULT hr;
HUGEP byte * plData;
hr = SafeArrayAccessData(*ppsaMyArray, (void HUGEP* FAR*)&plData);//取得数组数据
byte baa;
baa=plData[0];//第一个数据
SafeArrayUnaccessData(*ppsaMyArray);//取消数据访问
SafeArrayDestroy(*ppsaMyArray);//销毁
return 2;
}
将以下文本追加到 StdDLL.def 文件中现有文本:
Func2
VisualBasic中创建工程
添加以下声明代码,
Private Declare Function Func2 Lib"C:/StdDLL/Debug/StdDLL.dll" (MyArray() As Long) As Long ‘注意文件路径和你机器的一致
添加 Command1命令按钮,把以下代码附加到 Command 1 _ Click 事件过程中
Dim Result As Long
Dim MyArrayOfLongs(3) As Long
MyArrayOfLongs(0) = 0
MyArrayOfLongs(1) = 1
MyArrayOfLongs(2) = 2
Result = Func2(MyArrayOfLongs())
MsgBox ("Func2 returned " & Result)
四,注意问题
1) 在堆上创建SAFEARRAY数组
2) 一方创建,一方回收
3) 接收方不可以修改SAFEARRAY的数据,只能读或者销毁
源代码
http://www.ls-rj.cn