Оформлення класу у вигляді COM об’єкту в C + +, Різне, Програмування, статті

Оформлення класу у вигляді COM об’єкту.


Допустимо у вас є якийсь додаток, написаний на C + + (VC++ якщо бути коректним). Як воно у вас з’явилося не суть важливо, може бути це ваша стара розробка, може бути ви вирішили спочатку налагодити предметну частину. Важливо те що ви горите бажанням винести частину класів в об’єктні модулі і оформити їх у вигляді ActiveX, COM і ATL об’єктів. Є кілька типових проблем пов’язаних з таким переносом.


Множинні конструктори.

class MyCOM
{
MyCOM();
MyCOM(long id);
MyCOM(long id,LPCSTR Name);
:
}

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


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

/ / IMyCOM Стандартні обгортка спадкоємець від 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 немає автоматизації дозволяє створювати користувацькі типи поетом у все доведеться робити ручками

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*