使用ADO技术连接数据库时,经常要用到SAFEARRAY传递参数(我遇到的是向数据库添加数据时,有一种方法要用到SAFEARRAY)。我也是花了几天,断断续续的在看SAFEARRAY,刚开始的时候也是非常迷糊,不知道这是什么,只有照着书把代码敲到了电脑上,第二次还是不明白这些代码都做了什么,变量和参数都什么意思。今天下午在网上,书上包括直接在VS上看变量的定义,总算大概了解了点,基本掌握了一维数组的用法,下面是我自己对SAFEARRAY的理解,不当之处,还望之处,不懂之处,欢迎讨论。
首先要知道,SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。
一、要打包的数据和需要定义的变量
_variant_t vValue[4];
vValue[0] = _bstr_t("CSDN");
vValue[1] = _bstr_t("心中有道");
vValue[2] = _bstr_t("博客");
vValue[3] = _bstr_t("SAFEARRAY");
SAFEARRAY *psaValue;
SAFEARRAYBOUND rgsaBound[1];
VARIANT vsaValue;
二、各变量的意义
SAFEARRAY就是所谓的安全数组,psaValue是一个指向SAFEARRAY的指针,在VC中,SAFEARRAYBOUND的定义如下:
typedef struct tagSAFEARRAYBOUND
{
ULONG cElements;
LONG lLbound;
} SAFEARRAYBOUND;
typedef struct tagSAFEARRAYBOUND *LPSAFEARRAYBOUND;
SAFEARRAYBOUND是一个结构体,里面有两个变量,ULONG cElements表示的是元素的数目(更准确的说是在本维中的数目);LONG lLbound表示的是一个逻辑起点序号,实际访问内存的时候,安全数组会将程序指定的序号减去lLbound,比如你将其设置为10000,a[10000]这相当于A[0],a[999]数组越界,所以在没有特殊要求的情况下,lLbound一般为0。还有一点,定义的时候是SAFEARRAYBOUND rgsaBound[1], 这点要解释一下,rgsaBound[1]表示的是一位数组,二维数组要定义为rgsaBound[2],这里主要讲解一位数组,更高维数大家可以去搜一下,和一维的相似。
VARIANT vsaValue,这个就是最终要的得到的变量了,可以把这个变量作为参数传出去。
三、实现代码及函数、参数意义
psaValue = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);
for (long i = 0; i < 4; i++)
{
SafeArrayPutElement(psaValue, &i, &vValue[i]);
}
vsaValue.vt = VT_ARRAY | VT_VARIANT;
V_ARRAY(&vsaValue) = psaValue;
1、创建SAFEARRAY
psaValue = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);
第一个参数VT_VARIANT表示数组的类型,第二个参数表示创建数组的维数,本例中是一维,第三个参数是对这个数组各个维度的描述。
2、放置元素到数组中
for (long i = 0; i < 4; i++)
{
SafeArrayPutElement(psaValue, &i, &vValue[i]);
}
严格的来讲,这段代码只能在一维数组中使用,当然,如果一维数组够用的话,这个方法也挺方便的,下面这段代码是比较准确的:
long demen[1];
for (int i = 0; i < 4; i++)
{
demen[i] = i;
SafeArrayPutElement(psaValue, demen, &vValue[i]);
}
//如果是二维数组,应该这样
/*
long demen[2];
for (int i = 1; i < 4; i++) //假设是一个4*4的二维数组
{
for (int j = 1; j < 4; j++)
{
demen[0] = i;
demen[1] = j;
SafeArrayPutElement(psaValue, demen, &x);
}
}
*/
3、指明vsaValue存放值得类型
vsaValue.vt = VT_ARRAY | VT_VARIANT;
4、完成封装
V_ARRAY(&vsaValue) = psaValue; //等价于vsaValue.parray = psaValue
#define V_ARRAY(X) V_UNION(X, parray)
#define V_UNION(X, Y) ((X)->Y)
