COM編程的好處就是可以跨語言,我們公司是用C#做開發的,所以用C++去開發COM組件就可以彌補圖形渲染效能上的不足。但COM組件也有它的缺點,就是COM介面本身的調用開銷比較大,所以我總結了,使用COM組件最好是通過最少次數的介面調用來達到目的。所以數組的傳遞就至關重要了。打個最簡單的比方,調10000次SetX(
double x )花的時間肯定要比一次性把x數組傳進去SetX( double[] x )多的多。
普通的實值型別數組比如int[],short[]什麼的,這個都好說,COM裡都有對應的類型(VTS_PI4 VTS_PI2),而且就算是在C#裡也可以用Marshal來分配非託管數組然後傳遞到COM裡去進行操作。但字串數組不同,它每一項長度都不一樣,這給傳遞帶來了一些困難。所以今天主要就說說字串數組的傳遞。
在COM裡數組傳遞要用到一個叫做SAFEARRAY的東東封裝一下。但是如果直接用SAFEARRAY進行傳遞,那麼到C#裡面的參數類型是IntPtr,還是一個指標,這樣就給資料的擷取帶來不便。後來發現數組傳遞之前還要用VARIANT這個資料結構把SAFEARRAY再次封裝一下,這樣資料傳到C#裡後參數類型是Object,只需要用String[]強轉一下就OK了,十分方便。其實我這段描述百度百科裡好像也說的挺明白的,可以參考一下:http://baike.baidu.com/view/1907445.htm
我們可以這樣理解,SAFEARRAY就是存放資料的數組,而VARIANT就是一個殼子,就好比C#裡裝箱的概念一樣,把變數變成Object後傳遞起來會方便一些。說的夠多了,下面直接用代碼舉例了。
首先,如果數組是傳入參數的話,調度聲明中需要用VTS_VARIANT,函數原型聲明中類型是VARIANT*;如果是傳回值的話調度聲明要用VT_VARIANT,函數原型宣告類型是VARIANT(注意不是VARIANT*,和傳入參數有點不同,否則到C#裡參數類型不是Object而是IntPtr);然後主要說下數組的構造和封裝。
VARIANT AryWarp;
VariantInit( &AryWarp );
AryWarp.vt = VT_ARRAY | VT_BSTR;
// 指定殼子是用來封裝數組的,並且是字串數組,注意COM裡面字串就是BSTR,其實就是寬字元串
SAFEARRAY* psa;
SAFEARRAYBOUND bounds = { 10, 0 };
psa = SafeArrayCreate( VT_BSTR, 1, &bounds ); // 這裡就是初始化一個長度為10的字串數組
然後聲明一個字串數組 BSTR* bstrArray; 並且用SafeArrayAccessData將psa與bstrArray進行綁定(不知道綁定這個詞合適不合適,反正給我的感覺就是綁定),然後要做的就是對bstrArray[
i ]賦值了,賦值完畢後記得用SafeArrayUnaccessData解除綁定。
最後一步就是包殼子了,
AryWarp.parray = psa; 然後就可以把AryWarp return了。