1.作用
SafeArray是VB中的数组存储方式。通过SafeArray,可以在VC++和VB间相互调用
在ADO编程中经常使用。
主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成 SafeArray。
实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等信息。
SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。
在VARIANT的vt成员的值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。
SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。
2.实例
//(1). 定义变量,如:
int uIsRead = 10;
DOUBLE bVal[] = {0,1,2,3,4,5,6,7,8,9};
//(2). 创建SafeArray描述符:
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];// = {10,1};
rgsabound[0].cElements =uIsRead;
rgsabound[0].lLbound = 0;
psa = SafeArrayCreate(VT_R8,1,rgsabound);
//(3). 放置数据元素到SafeArray:
for(long index=0;index<=uIsRead;index++)
{
SafeArrayPutElement(psa,&index,&bVal[index ]);
}
//(4). 封装到VARIANT内:
varChunk->vt = VT_R8;
varChunk->parray = psa;
//(5)读取SafeArray中的数据的步骤:
DOUBLE buf[10];
for(long ind=0;ind<10;ind++)
{
::SafeArrayGetElement(pvar.parray,&ind,buf+ind);
}
double dou = 0;
for (long i = 0;i< 10;i++)
{
dou = buf[i];
}
3.常用的SafeArray处理函数
(1)建立SafeArray
SAFEARRAYBOUND arrbound [1]; //设置维度
arrbound [0]. lLbound = 0; //设置第一维的起始下标
arrbound [0]. cElements = ( long ) arrsize; //数组的长度
SAFEARRAY* SafeArrayCreate( //于建立多维普通数组
VARTYPE vt, //属性类型,一般设置为VT_VARIANT
unsigned intcDims, //维度
SAFEARRRAYBOUND *rgsabound //传入SAFEARRAYBOUND结构体来设置维度和数组长度
);
SAFEARRAY* SafeArrayCreateEx( //用于建立多维自定义类型或接口指针数组
VARTYPE vt,
unsigned int cDims,
SAFEARRRAYBOUND * rgsabound
PVOID pvExtra //用于创建自定义类型或COM对象的SafeArray数组
);
SAFEARRAY* SafeArrayCreateVector( //用于建立一维普通数组。
VARTYPE vt, //数组类型
long lLbound, //数组的最小下标(可以取负数)
unsigned int cElements //数组的长度
);
SAFEARRAY* SafeArrayCreateVectorEx( //用于建立一维自定义类型或接口指针数组。
VARTYPE vt,
long lLbound,
unsigned int cElements,
LPVOID pvExtra
);
//上面四个创建SAFEARRAY都返回一个指向SAFEARRAY*的指针,
//通过这个指针可以读写SafeArray中的数据,SafeArray使用完后必须释放。
//数组的最大下标的值是最小下标加上数组长度减一。
vt的取值如下表:
vt值 类型
VT_UI1 无符号1字节整数(BYTE)数组
VT_UI2 无符号2字节整数(WORD)数组
VT_UI4 无符号4字节整数(DWORD)数组
VT_UINT 无符号整数(UINT)数组
VT_INT 有符号整数(INT)数组
VT_I1 有符号1字节整数数组
VT_I2 有符号2字节整数数组
VT_I4 有符号4字节整数数组
VT_R4 IEEE 4字节浮点数(float)数组
VT_R8 IEEE 8字节浮点数(double)数组
VT_CY 8字节定点数货币值数组
VT_BSTR VB类型字符串数组
VT_DECIMAL 12字节定点数(大数字)数组
VT_ERROR 标准错误编号数组
VT_BOOL 布尔值数组
VT_DATE 日期型数组
VT_VARIANT Variant类型数组
SafeArrayCreateVectorEx函数中
pvExtra的含义和vt的取值有关。当vt的取值在上表中的时候,pvExtra的取值没有作用。
当vt取值VT_RECORD时,SafeArrayCreateVectorEx返回一个自定义类型(结构structure或联合union)的数组。这时,pvExtra必须是一个指向IRecordInfo的指针。
当vt取值是VT_UNKNOWN或VT_DISPATCH时。pvExtra是一个指向IID(接口GUID)的指针。在目前的COM规范中,pvExtra只能是IID_IUnknown和IID_IDispatch。并且必须和vt的取值一致。
(2)释放SafeArray数组
HRESULT SafeArrayDestroy( //释放SafeArray数组
SAFEARRAY * psa //创建时取得的指针作为参数
);
(3)访问数据
HRESULT SafeArrayAccessData( //获取SafeArray的数据指针,并锁定SafeArray数组的数据,在取得了数据指针之后,就可以直接访问SafeArray数组中的数据了
SAFEARRAY *psa,
void HUGEP** ppvData
);
HRESULT SafeArrayUnaccessData( //释放通过SafeArrayAccessData所取得的指针
SAFEARRAY * psa
);
(4)确定数组结构
HRESULT SafeArrayGetVartype (
SAFEARRAY* pSA, //pSA是传入的SAFEARRAY指针
VARTYPE *pVarType //取得类型,返回“VT_”开头的类型枚举值
);
(5)取得维数,返回数组的维数
UINT SafeArrayGetDim (
SAFEARRAY* pSA);
(6)取得每个维度的属性,返回指定维数(nDim)的上界和下界(nDim从1开始)
HRESULT SafeArrayGetLBound ( //取得nDim维度的上界
SAFEARRAY* pSA,
UINT nDim, //维度
long *pLBound //接收上界的指针
);
HRESULT SafeArrayGetUBound ( //取得nDim维度的下界
SAFEARRAY* pSA,
UINT nDim,
long *pUBound
);
(7)取得自定义类型接口,对于自定义结构数组,返回自定义结构类型数据的指针
HRESULT SafeArrayGetRecordInfo (
SAFEARRAY* pSA,
IRecordInfo ** ppRecordInfo //用于存放自定义结构类型数据的指针
);