SAFEARRAY与SAFEARRAYBOUND使用方法总结:
SAFEARRAY介绍:
SAFEARRAY的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。
实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等信息。SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,
然后才作为参数传送出去。在VARIANT的vt成员的值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。
SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。接下来我们来看看如何使用SafeArray 安全数组(字面翻译哈,别见怪)
方法一,包装一个SafeArray
(1). 定义变量,如:
VARIANT varChunk;uIsRead=f.Read(bVal,ChunkSize);//read array from a file. 写的比较简短,大意就是定义一文件对象,然后从中读取数据等。
if(uIsRead==0)break;rgsabound[0].lLbound = 0;
psa = SafeArrayCreate(VT_UI1,1,rgsabound);
(3). 放置数据元素到SafeArray:{
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_ BOOL WINAPI 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一个一个地读{
::SafeArrayGetElement(varChunk.parray,&index,buf+index); //就读到缓冲区buf里了。
}
方法二
用SafeArrayAccessData直接读写SafeArray缓冲区:
(1). 读缓冲区:SafeArrayUnaccessData(varChunk.parray);
//例子代码如下:
/** * this fucntion read database blob fileds to local file. */ _COMMON_API_ BOOL WINAPI 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; }