SafeArray用法
2018年日历-服装公司创业计划书
1 SafeArray的作用
使用SafeArray SafeArray是VB
中的数组存储方式。通过SafeArray,可以在
VC++和VB间相互调用。
Safe
Array也是Automation中的标准数组存储方式。SAFEARRAY的主要目的是
用于a
utomation中的数组型参数的传递。因为在网络环境中,数组是不能
直接传递的,而必须将其包
装成SafeArray。实质上SafeArray就是将通常
的数组增加一个描述符,说明其维数、
长度、边界、元 素类型等信息。
SafeArray也并不单独使用,而是将其再包装到VARIAN
T类型的变量中,然
后才作为参数传送出去。在VARIANT的vt成员的 值如果包含VT_ARR
AY|...,
那么它所封装的就是一个SafeArray,它的parray成员即是指向Safe
Array
的指针。 SafeArray中元素的类型可以是VARIANT能封装的任何类型,包<
br>括VARIANT类型本身。
将SafeArray包装到VARIANT变量中
SAFEARRAY *pSa;
VARIANT v1;
VariantInit(&v1);
= VT_I4 | VT_ARRAY;
Array of 4 byte integers
= pSa;
2
SafeArray结构体
typedef struct tagSAFEARRAY
{
unsigned short cDims;维数
unsigned short
fFeatures; 用来描述数组如何分配和如何被释放的标
志
unsigned
long cbElements; 数组元素的大小
unsigned long cLocks;
一个计数器,用来跟踪该数组被锁定的次数
void * pvData; 指向数据缓冲的指针
SAFEARRAYBOUND rgsabound[ 1 ];
描述数组每维的数组结构,该数组的
大小是可变的
} SAFEARRAY;
这个结构的成员(cDims,cLocks等)是通过API函数来设置和管理的。真
正的数
据存放在pvData成员中,而SAFEARRAYBOUND结构定义该数组结构的细节。
以下就是
该结构成员的简要描述:
rgsabound成员是一个SAFEARRAYBOUND结构的数组
--每个元素代表SAFEARRAY
的一个维。
typedef struct
tagSAFEARRAYBOUND
{
unsigned long
cElements; 每维中元素的个数
unsigned long lLbound;
} SAFEARRAYBOUND;
例如C语言中的数组int
a[3][4][5]用安全数组表示的时候则
cDims=3
;cbElements=sizeof(int)
元素
cElements lLbound
rgsabound[0] 3
0
rgsabound[1] 4
0
rgsabound[2] 5
0
3 SafeArray的初始化方法
方法一 利用SafeArrayAllocDe
scriptor和SafeArrayAllocData在堆上创建一
维数组。
long nData[10]={1,2,3,4,5,6,7,8,9,10};数据源
SAFEARRAY* pArray=NULL;
HRESULT
hr=SafeArrayAllocDescriptor(1,&pArray);
HRESULT SafeArrayAllocDescriptor
(
unsigned int
cDims
,
SAFEARRAY FAR* FAR*
ppsaOut
);
pArray->cbElements=sizeof(nData[0]);
pArray->rgsabound[0].cElements=10;
pArray->rgsabound[0].lLbound=0;
SafeArrayAllocData(pArray);
long*
pData=NULL;
SafeArrayAccessData(pArray,(void**)&pData);
long l(0),h(0);
SafeArrayGetLBound(pArray,1,&l);维数索引从1开始
HRESULT SafeArrayGetLBound
(
SAFEARRAY FAR* psa,
unsigned int nDim,
long FAR* plLbound
);
SafeArrayGetUBound(pArray,1,&h);
long Size=h-l+1;
SafeArrayAccessData(pArray,(void**)&pData);
for(long Idx=l;Idx
}
SafeArrayUnaccessData(pArray);
方法二 用
SafeArrayAllocDescriptor和SafeArrayAllocData在堆上创建二维
数组
SAFEARRAY* pArray=NULL;
HRESULT
hr=SafeArrayAllocDescriptor(2,&pArray)
pArray->rgsabound[0].lLbound=0;
pArray->rgsabound[0].cElements=3;
pData[Idx]=nData[Idx];
pArray->rgsabound[1].lLbound=0;
pArray->rgsabound[1].cElements=3;
pArray->cbElements=sizeof(long);
hr=SafeArrayAllocData(pArray);
赋初值
long Demen[2];
for(long i=0;i<3;++i)
{
for(long j=0;j<3;++j)
{
Demen[1]=i;
Demen[0]=j;
ong x=i*j;
SafeArrayPutElement(pArray,Demen,&x);
}
}
在SafeArrayPutElement
函数中需要注意的是如何指定所需元素。
SafeArrayPutElement 的第二个变量是一
指针,它指向数组各维的索引向量。最
右边的一维(最低位)放在向量的最前(index[0]);最
左边的一维(最低位)放在
向量的最后(index【cDims-1]】)。由于在C++中对多维数
组的访问正好与此相
反,所以需要特别注意这点。
即用SafeArrayPutElement对二维SAFEARRAY数组使用的时候下标要注意,
Demen[1]代表行,Demen[0]代表列。
访问二维数组
for(long i=0;i<3;++i)
{
for(long
j=0;j<3;++j)
{
Demen[1]=i;
}
Demen[0]=j;
long x(0);
SafeArrayGetElement(pArray,Demen,&x);
cout<<
}
SafeArrayDestroy(pArray);
在
SafeArrayPutElement 与 SafeArrayGetElement 函数的明显的局限
性在于
它们每次只能处理一个数值,在处理大量安全数组的数据时会极大地降低性能。
此时,可
以选择使用函数SafeArrayAccessData 和
SafeArrayUnaccessData。
SafeArrayAccessData 和
SafeArrayUnaccessData
将数组锁定在内存中,并返
回指向该安全数组数据的指针,这样便可以直接访问安全数组中的数据
例如
SafeArray* psa
long * pData;
long * pData;
SafeArrayAccessData(psa,
(LPVOID *)&pData);
Set or get any values in
the array.
*pData = 4;
*(pData + 1) = 5;
*(pData + 2) = 6;
*(pData + 3) = 7;
*(pData + 4) = 8;
*(pData + 5) = 9;
*(pData + 6) =10;
*(pData + 7) = 11;
Unlock the array.(pData is no longer valid.)
SafeArrayUnaccessData(pSa);
然后进行如下操作
index[0] = 3;
index[1] = 1;
SafeArrayGetElement(pSa, index, &NewData);
cout << NewData << endl; 则NewData的值为11
方法四:使用SafeArrayCreate在堆上创建一维数组
SAFEARRAYBOUND Bound[1];
Bound[0].lLbound=0;
Bound[0].cElements=10;
SAFEARRAY*
pArray=SafeArrayCreate(VT_I4,1,Bound);
long*
pData=NULL;
HRESULT
hr=SafeArrayAccessData(pArray,(void**)&pData);
long Low(0),High(0);
SafeArrayGetLBound(pArray,1,&Low);
SafeArrayGetUBound(pArray,1,&High);
long
Size=High-Low+1;
for(long
Idx=Low;Idx
}
SafeArrayUnaccessData(pArray);
SafeArrayDestroy(pArray);
pData[Idx]=Idx;
cout<
SAFEARRAYBOUND Bound[2];
Bound[0].lLbound=0;
Bound[0].cElements=3;
Bound[1].lLbound=0;
Bound[1].cElements=3;
SAFEARRAY*
pArray=SafeArrayCreate(VT_I4,2,Bound);
long
Demen[2];
for(long i=0;i<3;++i)
{
}
for(long
j=0;j<3;++j)
{
}
Demen[1]=i;
Demen[0]=j;
long x=i*j;
SafeArrayPutElement(pArray,Demen,&x);
访问二维数组
for(long i=0;i<3;++i)
{
}
SafeArrayDestroy(pArray);
for(long
j=0;j<3;++j)
{
}
Demen[1]=i;
Demen[0]=j;
long x(0);
SafeArrayGetElement(pArray,Demen,&x);
cout<<
根据MSDN中SafeArrayAllocDescriptor
allows the creation of safe arrays
that
contain elements with data types other than those
provided by
SafeArrayCreate. After creating an
array descriptor using
SafeArrayAllocDescriptor, set the
element size in the array descriptor,
an call
SafeArrayAllocData to allocate memory for the
array elements.(这
主要是因为在SafeArrayCreate函数中有一个Va
riant参数限定了data types)
访问SAFEARRAY:
方法一:使用SafeArrayAccessData方法
这种方法可以参见创建SAFEARRAY之方法一
请注意,访问完后要调用SafeArr
ayUnaccessData方法,并且调用
SafeArrayDestroy销毁数组,这种方式
通常用于访问一位数组
方法二:使用SafeArrayGetElement和SafeArrayPutElement
这种方法可以参见创建SAFEARRAY之方法五,这种方式在访问多维数组的时候很
有用