关于SafeArray的使用说明(转)

  猛料资料,首先介绍SafeArray使用,在介绍SafeArray中的结构。看完该节文章,SafeArray的陌生感一扫而去。编程

    SafeArray 在ADO编程中常常使用。它的主要目的是用于automation中的数组型参数的传递。由于在网络环境中,数组是不能直接传递的,而必须将其包装成 SafeArray。实质上SafeArray就是将一般的数组增长一个描述符,说明其维数、长度、边界、元素类型等信息。SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,而后才做为参数传送出去。在VARIANT的vt成员的值若是包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员便是指向SafeArray的指针。SafeArray中元素的类型能够是VARIANT能封装的任何类型,包括VARIANT类型自己。 数组

使用SafeArray的具体步骤:安全

方法一:网络

 包装一个SafeArray:函数

(1)定义变量,如:spa

   VARIANT varChunk;指针

   SAFEARRAY *psa;orm

   SAFEARRAYBOUND rgsabound[1];对象

(2) 建立SafeArray描述符:内存

 //read array from a file.

 uIsRead=f.Read(bVal,ChunkSize);

 if(uIsRead==0)

break;

 rgsabound[0].cElements = uIsRead;

 rgsabound[0].lLbound = 0;

 psa = SafeArrayCreate(VT_UI1,1,rgsabound);

(3)放置数据元素到SafeArray:

 for(long index=0;index<uIsRead;index++)         

 {

    if(FAILED(SafeArrayPutElement(psa,&index,&bVal[index])))

    ::MessageBox(NULL,"出毛病了。","提示",MB_OK | MB_ICONWARNING);

  }

 一个一个地放,挺麻烦的。

(4)封装到VARIANT内:

   varChunk.vt = VT_ARRAY|VT_UI1;

   varChunk.parray = psa;

 这样就能够将varChunk做为参数传送出去了。

读取SafeArray中的数据的步骤:

(1)用SafeArrayGetElement一个一个地读

 BYTE buf[lIsRead];

 for(long index=0; index<lIsRead; index++)        

 {          

    ::SafeArrayGetElement(varChunk.parray,&index,buf+index);  

 }

 就读到缓冲区buf里了。

方法二:

 使用SafeArrayAccessData直接读写SafeArray的缓冲区:

(1)读缓冲区:

 BYTE *buf;

 SafeArrayAccessData(varChunk.parray, (void **)&buf);

 f.Write(buf,lIsRead);

 SafeArrayUnaccessData(varChunk.parray);

(2)写缓冲区:

 BYTE *buf;

 ::SafeArrayAccessData(psa, (void **)&buf);

 for(long index=0;index<uIsRead;index++)         

 {

     buf[index]=bVal[index]; 

 }

 ::SafeArrayUnaccessData(psa);

 varChunk.vt = VT_ARRAY|VT_UI1;

 varChunk.parray = psa;

   

    这种方法读写SafeArray均可以,它直接操纵SafeArray的数据缓冲区,比用SafeArrayGetElement和 SafeArrayPutElement速度快。特别适合于读取数据。但用完以后不要忘了调用::SafeArrayUnaccessData (psa),不然会出错的。

如下就是SAFEARRAY的Win32定义:

  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结构定义该数组结构的细节。如下就是该结构成员的简要描述:

成员

描述

cDims

数组的维数

fFeatures

用来描述数组如何分配和如何被释放的标志

cbElements

数组元素的大小

cLocks

一个计数器,用来跟踪该数组被锁定的次数

pvData 

指向数据缓冲的指针

rgsabound

描述数组每维的数组结构,该数组的大小是可变的

 rgsabound是一个有趣的成员,它的结构不太直观。它是数据范围的数组。该数组的大小依safe array维数的不一样而有所区别。rgsabound成员是一个SAFEARRAYBOUND结构的数组--每一个元素表明SAFEARRAY的一个维。

  typedef struct tagSAFEARRAYBOUND

   {

    unsigned long cElements;

    unsigned long lLbound;

   } SAFEARRAYBOUND;

  维数被定义在cDims成员中。例如,一个\'C\'类数组的维数能够是[3][4][5]-一个三维的数组。若是咱们使用一个SAFEARRAY来表示这个结构,咱们定义一个有三个元素的rgsabound数组--一个表明一维。

  cDims = 3;

    ...

  SAFEARRAYBOUND rgsabound[3];

  rgsabound[0]元素定义第一维。在这个例子中ILBOUND元素为0,是数组的下界。cElements成员的值等于三。数组的第二维 ([4])能够被rgsabound结构的第二个元素定义。下界也能够是0,元素的个数是4,第三维也是这样。

   要注意,因为这是一个"C"数组,所以由0 开始,对于其它语言,例如Visual Basic,或者使用一个不一样的开始。该数组的详细状况以下所示:

元素

cElements

ILbound

rgsabound[0] 

0

rgsabound[1]

0

rgsabound[2]

5

0

   关于SAFEARRAYBOUND结构其实还有不少没说的。咱们将要使用的SAFEARRAY只是一个简单的单维字节数组。咱们经过API函数建立数组的时候,SAFEARRAYBOUND将会被自动设置。只有在你须要使用复杂的多维数组的时候,你才须要操做这个结构。

  还有一个名字为cLocks的成员变量。很明显,它与时间没有任何的关系--它是一个锁的计数器。该参数是用来控制访问数组数据的。在你访问它以前,你必须锁定数据。经过跟踪该计数器,系统能够在不须要该数组时安全地删除它。 

建立SAFEARRAY

  建立一个单维SAFEARRAY的简单方法是经过使用SafeArrayCreateVector API函数。该函数可分配一个特定大小的连续内存块。

  SAFEARRAY *psa;

  //  create a safe array to store the stream data

  //  llen is the number of bytes in the array.

  psa = SafeArrayCreateVector( VT_UI1, 0, llen );

   SafeArrayCreateVector API建立一个SAFEARRAY,而且返回一个指向它的指针。首个参数用来定义数组的类型--它能够是任何有效的变量数据类型。为了传送一个串行化的对 象,咱们将使用最基本的类型--一个非负的字节数组。VT--UI1表明非负整形的变量类型,1个字节。

  常数\'0\'定义数组的下界;在C++中,一般为0。最后的参数llen定义数组元素的个数。在咱们的例子中,这与咱们将要传送对象的字节数是同样的。咱们尚未提数组大小(llen)是怎样来的,这将在咱们从新考查串行化时说起。

  在你访问SAFEARRAY数据以前,你必须调用SafeArrayAccessData。该函数锁定数据而且返回一个指针。在这里,锁定数组意味着增长该数组的内部计数器(cLocks)。

  //  define a pointer to a byte array

  unsigned char *pData = NULL;

  SafeArrayAccessData( psa, (void**)&pData );

   ... use the safe array

  SafeArrayUnaccessData(psa);

  相应用来释放数据的函数是SafeArrayUnaccessData(),该功能释放该参数的计数。

相关文章
相关标签/搜索