SAFEARRAY与SAFEARRAYBOUND的相关知识点
最近搞数据库方面的一个小程序,将本地文件传输到服务器保存起来,其中对于文件的发送使用的是ADO中的AppendChunck函数,其参数为VARIANT类型的,使用常用方法将SafeArray 封装到VARIANT参数中。。。所以需要了解下SafeArray相关的一些知识。
SAFEARRAY的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元 素类型等信息。SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。在VARIANT的vt成员的 值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。 SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。为什么叫安全数组呢? 是因为SAFEARRAY这样定义结构的作用是实现COM API函数可以限制我们访问越界的元素和其他一些并不安全操作数组的行为等。
包装一个SafeArray的步骤如下:
1 VARIANT varBLOB; 2 SAFEARRAY *psa; 3 SAFEARRAYBOUND rgsabound[1]; 4 5 // pBuf是之前已经读入数据的缓冲区 Byte* 6 if(pBuf) 7 { 8 // 1 9 /*创建safeArray的描述符safearraybound*/ 10 rgsabound[0].lLbound = 0; 11 rgsabound[0].cElements = nSize; 12 psa = SafeArrayCreate(VT_UI1, 1, rgsabound); 13 14 // 2 15 // 这里将数据一个字节一个字节进行复制 16 for (long i = 0; i < (long)nSize; i++) 17 SafeArrayPutElement (psa, &i, pBuf++); 18 19 // 3 20 /*将safeArray封装到VARIANT中*/ 21 varBLOB.vt = VT_ARRAY | VT_UI1; 22 varBLOB.parray = psa; 23 }
这样我们就可以直接使用VARIANT类型数据了。而其中我们看到还使用了一个SafeArrayBound数组,其实它是SafeArray的描述符,其大小依据SafeArray的维数而不同。rgsabound成员是一个SAFEARRAYBOUND结构的数组--每个元素代表SAFEARRAY的一个维。
1 typedef struct tagSAFEARRAYBOUND 2 { 3 unsigned long cElements; 4 unsigned long lLbound; 5 } SAFEARRAYBOUND;
其中lLbound是该维的数组存取的下限,一般为0,而cElements是该维的长度,比如C语言中array[2][3]的数组的话,该数组为二维,则其对应的safebound数组则有两个元素,即 rgsabound[] == {2,0};
rgsabound[] == {5,0};
参考资料: SafeArrayBound------http://msdn.microsoft.com/en-us/library/windows/desktop/ms221167(v=vs.85).aspx
SafeArray--------http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms221482(v=vs.85).aspx