SAFEARRAY与SAFEARRAYBOUND用法

来源:互联网 发布:mac下搭建lamp环境 编辑:程序博客网 时间:2024/06/05 01:29

SAFEARRAY与SAFEARRAYBOUND使用方法总结:


SAFEARRAY介绍:

SAFEARRAY的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。

实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等信息。SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,

然后才作为参数传送出去。在VARIANT的vt成员的值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。

SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。接下来我们来看看如何使用SafeArray 安全数组(字面翻译哈,别见怪)


使用SafeArray的具体步骤:

方法一,包装一个SafeArray 

(1). 定义变量,如:

    VARIANT varChunk;
 SAFEARRAY *psa;   
    SAFEARRAYBOUND rgsabound[1]; 

(2). 创建SafeArray描述符: 

 uIsRead=f.Read(bVal,ChunkSize);//read array from a file. 写的比较简短,大意就是定义一文件对象,然后从中读取数据等。 

 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)))  //一个一个地放,挺麻烦的。

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

    } 

(4). 封装到VARIANT内: 
   varChunk.vt = VT_ARRAY|VT_UI1;  
   varChunk.parray = psa;  

   这样就可以将varChunk作为参数传送出去了。

(5).销毁创建的SafeArray 安全数组
     SafeArrayDestroyData(safeArray);
     SafeArrayDestroy(safeArray);


//例子代码如下:

/*

  * this function read local file to blob fileds.

*/

_COMMON_API_ BOOLWINAPI ReadPathFileToBlob(_RecordsetPtr& rs,LPCTSTR sField,LPCTSTR lpFilePath){BOOL bFlag = TRUE;CFile file;if (file.Open(lpFilePath,CFile::modeRead | CFile::typeBinary)){long lLen = file.GetLength();if (lLen > 0){byte* lpFileBuffer = new byte[lLen+1];ASSERT(lpFileBuffer != NULL);memset(lpFileBuffer,0,lLen+1);file.Read(lpFileBuffer,lLen);file.Close();SAFEARRAYBOUND sArrayBound[1];sArrayBound[0].lLbound= 0;sArrayBound[0].cElements= lLen;SAFEARRAY *safeArray = NULL; safeArray = SafeArrayCreate(VT_UI1, 1, sArrayBound);ASSERT(safeArray != NULL);for (long i = 0; i < lLen; i++)SafeArrayPutElement(safeArray, &i, lpFileBuffer++);VARIANT varBLOB;varBLOB.vt = VT_ARRAY | VT_UI1;varBLOB.parray = safeArray;rs->GetFields()->GetItem(sField)->AppendChunk(varBLOB);SafeArrayDestroyData(safeArray);SafeArrayDestroy(safeArray);}}else{bFlag = FALSE;}return bFlag;}



续集:  

  读取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); 

//例子代码如下:

/**  * this fucntion read database blob fileds to local file.*/_COMMON_API_ BOOLWINAPI ReadBlobToLocalFile(_RecordsetPtr& rs,LPCTSTR sField,LPCTSTR lpFilePath){BOOL bFlag = TRUE;long lDataSize = rs->GetFields()->GetItem(sField)->ActualSize;if (lDataSize > 0){_variant_t varBLOB = rs->GetFields()->GetItem(sField)->GetChunk(lDataSize);if ((VT_ARRAY | VT_UI1) == varBLOB.vt){/*BYTE lpFileBuffer[lDataSize+1];memset(lpFileBuffer,0,lDataSize+1);for (long l = 0 ; l < lDataSize ; l++)SafeArrayGetElement(varBLOB.parray,&l,lpFileBuffer++);*/char* buffer = NULL;SafeArrayAccessData(varBLOB.parray,(void **)&buffer);::DeleteFile(lpFilePath);CFile file;if (file.Open(lpFilePath,CFile::modeCreate | CFile::modeWrite | CFile::typeBinary)){file.Write(buffer,lDataSize);file.Close();}else{bFlag = FALSE;}SafeArrayUnaccessData(varBLOB.parray);}else{bFlag = FALSE;}}else{bFlag = FALSE;}return bFlag;}




这种方法读写SafeArray都可以,它直接操纵SafeArray的数据缓冲区,比用SafeArrayGetElement和 SafeArrayPutElement速度快。

特别适合于读取数据。但用完之后不要忘了调用::SafeArrayUnaccessData (psa),否则会出错的。  
0 0