COM組件中使用用戶自定義數據類型
2002-05-20· ·lostall··COM集中營
(1) 從IUnknown繼承的自定義接口
把數據結構直接傳送給基於VTable接口的方法,只適用於由MIDL編譯生成的proxy/stub DLL調度的接口,不能用於Invoke();(參UserDefinedDataType(1))
a.在一個新的.h文件中定義自定義數據結構.
b.在.idl文件最前面加入這個.h文件,比如:
#include "MyStruct.h"
c.給從IUnknown派生的接口加入使用了自定義數據結構的方法。
d.在客戶程序的stadafx.h最下面加入#import指令,如:
#import "../test3.tlb" no_namespace
在生成的.tlh文件中,會自動包含了用戶自定義數據結構的定義。
e.在客戶程序需要的時侯調用組件接口函數。
整個過程非常簡單,與使用一般的自定義數據類型無異。
另外也可以很方便的使用自定義數據結構數組,使用方法如下:
HRESULT Test2([in]int nCount, [in, size_is(nCount)]MyStruct *pStruct)
(2)從IDispatch繼承的雙接口
對於從IDispatch繼承的雙接口就不能象方法一那樣直接在接口方法裏申請自定義類型了,因爲雙接口必須要用與自動化兼容的類型。所以採用以下的步驟。
(參UserDefinedDataType(2))
a.首先在.idl文件中加入如下幾句,定義一個自定義數據類型。
typedef [ uuid(44ABAE82-A173-11d4-98DB-0080C8F5B2E4)]
struct MyStruct
{
int x;
int y;
}MyStruct;
b.接口方法參數定義爲VARIANT類型,指針也一樣。
c.客戶端通過ClassWiard導入類型庫(用#import也可以,不過這裏要驗證自動化)
d.客戶程序中要加入MyStruct的定義
e.客戶程序中加入以下代碼:
const GUID GUID_MyStruct=
{0x44ABAE82,0xA173,0x11d4,{0x98,0xDB,0x00,0x80,0xC8,0xF5,0xB2,0xE4}};
const GUID LIBID_TEST6Lib =
{0x67061661,0xa2cb,0x11d4,{0x98,0xdb,0x00,0x80,0xc8,0xf5,0xb2,0xe4}};
ITypeLib* pTypeLib=NULL;
ITypeInfo* pTypeInfo=NULL;
IRecordInfo* pRecordInfo=NULL;
LoadRegTypeLib(LIBID_TEST6Lib, 1, 0, LANG_NEUTRAL, &pTypeLib);
pTypeLib->GetTypeInfoOfGuid(GUID_MyStruct, &pTypeInfo);
GetRecordInfoFromTypeInfo(pTypeInfo, &pRecordInfo);
MyStruct *pMyStruct = new MyStruct;
pMyStruct->x = pMyStruct->y = 100;
VARIANT vr;
VariantInit(&vr);
vr.vt = VT_RECORD; //表明自定義類型
vr.pvRecord = (PVOID)pMyStruct; //指向實際數據
vr.pRecInfo = pRecordInfo; //包含了數據的一些信息
test6.Test2(vr); //調用接口方法
pTypeLib->Release();
pTypeInfo->Release();
pRecordInfo->Release();
f.在服務器組件接口方法的實現中加入以下幾句:
if (vr.vt == VT_RECORD)
{
IRecordInfo *pRecordInfo = vr.pRecInfo;
PVOID pMyStruct = vr.pvRecord;
VARIANT varX, varY;
int x=0, y=0;
VariantInit(&varX);
VariantInit(&varY);
pRecordInfo->GetField(pMyStruct, L"x", &varX);//獲得x字段的值
if (varX.vt == VT_INT)
{
x = varX.intVal;
}
pRecordInfo->GetField(pMyStruct, L"y", &varY);//獲得y字段的值
if (varX.vt == VT_INT)
{
y = varY.intVal;
}
}
補:
a.通過VARIANT,VT_RECORD,IRecordInfo的這種方法可以用自動化來傳遞自定義類型數據,但實際上這種方法只適用於雙接口的情況。其原因在於實現組件IDispatch接口的IDispatchImpl類身上,它是通過VTable來調用方法的。如果是純Dispatch接口就不能用這種方法,而我經過試驗,暫時無法用這種方法實現dispinterface的情況。
b.同樣的方法適用於安全數組,如果傳遞一個自定義數據結構的數組,則要用到SAFEARRAY,注意用類似SafeArrayCreateEx(VT_RECORD,1,&rgbounds,pRecInfo)的方法來創建數組。
(3)用dispinterface說明的純IDispatch接口暫時沒找到方法。