標籤:mfc safearray variant
使用ADO技術串連資料庫時,經常要用到SAFEARRAY傳遞參數(我遇到的是向資料庫添加資料時,有一種方法要用到SAFEARRAY)。我也是花了幾天,斷斷續續的在看SAFEARRAY,剛開始的時候也是非常迷糊,不知道這是什麼,只有照著書把代碼敲到了電腦上,第二次還是不明白這些代碼都做了什麼,變數和參數都什麼意思。今天下午在網上,書上包括直接在VS上看變數的定義,總算大概瞭解了點,基本掌握了一維數組的用法,下面是我自己對SAFEARRAY的理解,不當之處,還望之處,不懂之處,歡迎討論。
首先要知道,SafeArray也並不單獨使用,而是將其再封裝到VARIANT類型的變數中,然後才作為參數傳送出去。
一、要打包的資料和需要定義的變數
<span style="white-space:pre"></span>_variant_t vValue[4];vValue[0] = _bstr_t("CSDN");vValue[1] = _bstr_t("心中有道");vValue[0] = _bstr_t("部落格");vValue[0] = _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,這個就是最終要的得到的變數了,可以把這個變數作為參數傳出去。
三、實現代碼及函數、參數意義
<span style="white-space:pre"></span>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
<span style="white-space:pre"></span>psaValue = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);
第一個參數VT_VARIANT表示數組的類型,第二個參數表示建立數組的維數,本例中是一維,第三個參數是對這個數組各個維度描述。SafeArrayCreate()就是建立SAFEARRAY的函數,準確的說是在堆中建立了一個SAFEARRAY,也就是說在這個函數裡面,調用了new或者malloc()之類的申請了一個空間(我有個疑問是這個空間是否需要自己用delete釋放,C++學的不好,對這不太清楚)。還有一些函數是在棧(也就是臨時變數)中實現了SAFEARRAY,這個函數我還沒瞭解,就不在這討論了。2、放置元素到數組中
<span style="white-space:pre"></span>for (long i = 0; i < 4; i++){SafeArrayPutElement(psaValue, &i, &vValue[i]);}
嚴格的來講,這段代碼只能在一維數組中使用,當然,如果一維數組夠用的話,這個方法也挺方便的,下面這段代碼是比較準確的:
<span style="white-space:pre"></span>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);}}*/
第一個參數是指向SAFEARRAY的指標;第二個參數是long型數組指標,表示SAFEARRAY元素的下標,即唯一確定一個SAFEARRAY元素;第三個參數就是要放置的那個值得指標了。3、指明vsaValue存放值得類型
<span style="white-space:pre"></span>vsaValue.vt = VT_ARRAY | VT_VARIANT;
在VARIANT的vt成員的值如果包含VT_ARRAY,那麼它所封裝的就是一個SAFEARRAY,它的parray成員即是指向SAFEARRAY的指標。
VT_ARRAY說明vsaValue封裝的是一個SAFEARRAY,VT_VARIANT說明SAFEARRAY的元素是VARIANT類型。4、完成封裝
<span style="white-space:pre"></span>V_ARRAY(&vsaValue) = psaValue;<span style="white-space:pre"></span>//等價於<span style="white-space:pre">vsaValue.parray = psaValue;</span>
V_ARRAY()是VC中的一個宏,定義如下:
#define V_ARRAY(X) V_UNION(X, parray)#define V_UNION(X, Y) ((X)->Y)
到這也算差不多了,第一次在CSDN上寫一個講解,紀念一下