WINDOWS-基础:SafeArray的使用方法

1 SafeArray的作用

  •   使用SafeArray SafeArray是VB中的数组存储方式。通过SafeArray,可以在VC++和VB间相互调用。
  •   SafeArray也是Automation中的标准数组存储方式。SAFEARRAY的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray
  •   实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元 素类型等信息。
  •   SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。
  •   在VARIANT的vt成员的值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针
  •   SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。

将SafeArray包装到VARIANT变量中

SAFEARRAY *pSa;

VARIANT v1;

VariantInit(&v1);

v1.vt = VT_I4 | VT_ARRAY; // Array of 4 byte integers

v1.parray = 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的初始化方法

方法一 利用SafeArrayAllocDescriptor和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<Size;++Idx) { }

SafeArrayUnaccessData(pArray); pData[Idx]=nData[Idx];

 

方法二 用SafeArrayAllocDescriptor和SafeArrayAllocData在堆上创建二维数组

SAFEARRAY* pArray=NULL;

HRESULT hr=SafeArrayAllocDescriptor(2,&pArray)

pArray->rgsabound[0].lLbound=0;

pArray->rgsabound[0].cElements=3;

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;

}

}

 

  在SafeArrayPutElement 函数中需要注意的是如何指定所需元素。SafeArrayPutElement 的第二个变量是一指针,它指向数组各维的索引向量。最右边的一维(最低位)放在向量的最前(index[0]);最左边的一维(最低位)放在向量的最后(index【cDims-1]】)。由于在C++中对多维数组的访问正好与此相反,所以需要特别注意这点。

  即用SafeArrayPutElement对二维SAFEARRAY数组使用的时候下标要注意, Demen[1]代表行,Demen[0]代表列。 Demen[0]=j; ong x=i*j; SafeArrayPutElement(pArray,Demen,&x);

访问二维数组

for(long i=0;i<3;++i)

{

for(long j=0;j<3;++j)

{

http://9455.net九九文章网

} Demen[1]=i; Demen[0]=j; long x(0); SafeArrayGetElement(pArray,Demen,&x); cout<<"("<<i<<","<<j<<") "<<x<<endl; }

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<Size;++Idx) { } SafeArrayUnaccessData(pArray);
SafeArrayDestroy(pArray);
pData[Idx]=Idx;
cout<<pData[Idx]<<endl;

方法五:使用SafeArrayCreate在堆上创建二维数组

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<<"("<<i<<","<<j<<") "<<x<<endl;

  根据MSDN中SafeArrayAllocDescriptor allows the creation of safe arrays that contain elements with data types other than those provided by After creating an array descriptor using SafeArrayAllocDescriptor, set the element

posted @ 2013-12-05 15:40  CPYER  阅读(1766)  评论(0编辑  收藏  举报