РефератыИнформатика, программированиеОфОформление класса в виде COM объекта в C++

Оформление класса в виде COM объекта в C++

Оформление класса в виде COM объекта.


Допустим у вас есть некоторое приложение, написанное на C++(VC++ если быть корректным). Как оно у вас появилось не суть важно, может быть это ваша старая разработка, может быть вы решили сначала отладить предметную часть. Важно то что вы горите желанием вынести часть классов в объектные модули и оформить их в виде ActiveX, COM и ATL объектов. Есть несколько типовых проблем связанных с таким переносом.


Множественные конструкторы.


class MyCOM


{


MyCOM();


MyCOM(long id);


MyCOM(long id,LPCSTR Name);


:


}


Знакомо и очень удобно, но в COM правила создания объекта строго определены и ни одна из функции для созданий объектов не позволяет передавать параметры конструктору класса.


Настройку объекта придется вынести в отдельный метод например Init.


// IMyCOM cтандартная обертка наследник от COleDispatchDriver


IMyCOM * d=new IMyCOM;


COleException pErr;


CString SSS="Mylib.MyCOM";


d->CreateDispatch( SSS,&pErr);


d->Init(15,"Матрица"); // Инициализируем


В принципе вы можете создать свою фабрику объектов. Это позволит создавать объекты вот так.


IMyOF * d=new IMyOF;


COleException pErr;


CString SSS="MyLib.MyOF";


d->CreateDispatch( SSS,&pErr);


IMyCOM Ob1(d->CraeteEmpty());


IMyCOM Ob2(d->CraeteId(15));


IMyCOM Ob3(d->CraeteFull(15,SSS ));


Но зачем вам лишний промежуточный объект если можно обойтись без него.


Перегруженные методы.


class MyCOM


{


:


LPCSTR GetMyRec(long id);


LPCSTR GetMyRec(LPCSTR Name);


AddRec ();


AddRec (long id);


AddRec (long id, LPCSTR Name);


:.


}


Это вполне законный код С++, но COM не разрешит вам в интерфейсе объявить два метода с одним именем. Это противоречит концепции.


Решение


Можно связать функции с разными методами интерфейса для этого в odl пишим


[id(1)] BSTR AddRecName(BSTR ID);


[id(2)] BSTR AddRecID(long ID);


а в cpp осуществляем привязку.


BEGIN_DISPATCH_MAP(:.)


DISP_FUNCTION(CPSDG, "AddRecName", AddRec, VTS_BSTR, VTS_BSTR)


DISP_FUNCTION(CPSDG, "AddRecId", AddRec, VTS_BSTR, VTS_I2)


DISP_FUNCTION_ID(:.)


END_DISPATCH_MAP()


Можно написать прокси функции. Например для GetMyRec прототип может выглядеть так


LPCSTR GetMyRec (VARIANT id)


{


switch id.vt


{case VT_I4: { return GetMyRec(id.lVal); }


case VT_BSTR: { return GetMyRec(id.bstrVal); }


}


return S_OK;


}


Для функции AddRec можно сделать вот так


HRESULT AddRec (VARIANT id, VARIANT Name)


{


if ((id.vt==VT_EMPTY)&&(Name.vt==VT_EMPTY))

>

{AddRec() ; return S_OK;}


if ((id.vt==VT_I4)&&(Name.vt==VT_EMPTY))


{AddRec(id.lVal) ; return S_OK;}


if ((id.vt==VT_I4)&&(Name.vt== VT_BSTR))


{AddRec(id.lVal, Name. bstrVal ) ; return S_OK;}


:


}


Этого вполне достаточно, но можно еще изменить объявление метода интерфейса в odl вот так


HRESULT Add(VARIANT [optional, in]id, [optional,in]VARIANT S);


это позволит вызывать метод , более красиво.


Пример на VB


MyObject.Add // Любой из вариантов должен работать


MyObject.Add 15


MyObject.Add 15, "Var"


Пользовательские типы данных


В сложном проекте полно собственных констант, структур, множеств используемых в качестве параметров .


#define IDL_NEXT 5


#define IDL_STOP 6


:


struct UDT


{


unsigned long X;


unsigned long Y;


BSTR pbstr;


} UDT;


:


typedef enum EnumType


{


First=1,


Seond=4,


Last =10


};


class MyCOM


{


:.


void SetType (EnumType T);


void Do(UDT * Dat);


void SetMove (int val);


:.


}


:


// а где то все это вызывается


SetType(First);


UDT Dat,Dat1;


:


Do (&Dat,Dat1);


SetMove (IDL_NEXT);


Понятно что, для того чтобы подобным образом можно было вызывать методы COM объекта, служебные структуры, множества и константы должны быть доступны из вне.


Для этого нужно включить их описание в ODL файл.


Множества описываются так.


[


uuid(...),


version(1.0),


helpstring("...")


]


library LibraryName


{


importlib("stdole32.tlb");


importlib("stdole2.tlb");


typedef enum


{


valueName1 = 0,


valueName2 = 1,


...


valueNameN = N


} EnumType;


..


}


Передавать в качестве параметров структуры тоже можно. Такие структуры называются UDT - User Defined Type. В IDL описываютсятак:


Typedef [uuid(C1D3A8C0-A4AA-11D0-819C-00A0C90FFFC3)] struct UDT


{


unsigned long X;


unsigned long Y;


BSTR pbstr;


} UDT;


Описывать параметры метода можно как VARIANT но тогда придется работать с интерфесом IRecordInfo или как UDT:


Do([in]UDT* pIn, [in,out] pOut);


Передать UDT в такой метод проще простого:


UDT some_data, some_returned_data;


p->Do(&some_data, some_returned_data);


Членами UDT могут быть другие UDT или oleautomation-совместимые типы.


У вы в VC нет автоматизации позволяющей создавать пользовательские типы поэтом у все придется делать ручками

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Оформление класса в виде COM объекта в C++

Слов:643
Символов:6514
Размер:12.72 Кб.