У меня есть проект в котором имеется некоторая иерархия классов.
class Ycl
{
int value;
public:
...
int GetValue(void){return value;}
void SetValue(int nv){value=nv;}
};
class Xcl
{
Ycl *y;
...
public:
Ycl &Item(int i){return y[i];}
};
В С++ я могу написать так
Xcl x;
x.Item(1).SetValue(10);
Мне необходима обертка (COM,ATL)
чтобы я мог также писать и в VB
x.Item(1).value=10
Не поможет ли кто с примером ?
Пробовал написать по примерам с ATL, но я пока не понимаю всю картину вцелом
и поэтому смущает, что каждый раз когда я вызываю метод Item
у меня каждый раз создается и инициализируется объект
STDMETHODIMP CComXcl::Item(short n, LPDISPATCH *retval)
{
CComObject<CComYcl>* p = new CComObject<CComYcl>;
p->DoNotForgetInitItem();
IDispatch* pDisp;
HRESULT res=p->QueryInterface(IID_IDispatch, (void**)&pDisp);
if (res != S_OK) return E_POINTER;
*retval = pDisp;
return S_OK;
}
Ц>Пробовал написать по примерам с ATL, но я пока не понимаю всю картину вцелом Ц>и поэтому смущает, что каждый раз когда я вызываю метод Item Ц>у меня каждый раз создается и инициализируется объект
Ц>
Ц>STDMETHODIMP CComXcl::Item(short n, LPDISPATCH *retval)
Ц>{
Ц> CComObject<CComYcl>* p = new CComObject<CComYcl>;
Ц> p->DoNotForgetInitItem();
Ц> IDispatch* pDisp;
Ц> HRESULT res=p->QueryInterface(IID_IDispatch, (void**)&pDisp);
Ц> if (res != S_OK) return E_POINTER;
Ц> *retval = pDisp;
Ц> return S_OK;
Ц>}
Ц>
Ц>Может быть его надо где-то сохранять ?
Да. В статическом члене. Типа
// где- то в *.h, в определении классаstatic map<short, CComPtr<IDispatch> arrayItems;
STDMETHODIMP CComXcl::Item(short n, LPDISPATCH *retval)
{
...
if(arrayItems.find(n) != arrayItems.end()) {
CComObject<CComYcl>* p = new CComObject<CComYcl>;
p->DoNotForgetInitItem();
IDispatch* pDisp;
HRESULT res=p->QueryInterface(IID_IDispatch, (void**)&pDisp);
if (res != S_OK) {
return E_POINTER;
}
arrayItems[n] = pDisp;
*retval = pDisp;
return S_OK;
} else {
*retval = arrayItems[n].Detach();
return S_OK;
}
}
Писал без компилятора, могут быть ошибки. Но где-то так.
Я так понимаю, что и Xcl и Ycl имеют обёртки в СОМ. Тогда n-ый элемент у тебя уже есть, его не надо создавать заново.
Ц>Пробовал написать по примерам с ATL, но я пока не понимаю всю картину вцелом и поэтому смущает, что каждый раз когда я вызываю метод Item у меня каждый раз создается и инициализируется объект
Ц>STDMETHODIMP CComXcl::Item(short n, LPDISPATCH *retval)
Ц>{
Ц> CComObject<CComYcl>* p = new CComObject<CComYcl>;
Ц> p->DoNotForgetInitItem();
Ц> IDispatch* pDisp;
Ц> HRESULT res=p->QueryInterface(IID_IDispatch, (void**)&pDisp);
Ц> if (res != S_OK) return E_POINTER;
Ц> *retval = pDisp;
Ц> return S_OK;
Ц>}
Ц>Может быть его надо где-то сохранять ?
Так он у тебя есть, его и сохранять-то не надо. Вот примерно так.
STDMETHODIMP CComXcl::Item(short n, LPDISPATCH *retval)
{
// нужен анализ невыхода за границы массива y
// y[n] - это объект-обёртка Ycl, значит, имеет QueryInterfacereturn y[n].QueryInterface(IID_IDispatch, (void**)&pDisp);
}
Попробовал, получилось, спасибо.
Правда вместо arrayItems[n].Detach() использовал arrayItems[n].CopyTo(retval);
иначе при последующих обращениях -- Cannot evaluate to an object
GS>> CComObject<CComYcl>* p = new CComObject<CComYcl>;
GS>> p->DoNotForgetInitItem();
GS>> IDispatch* pDisp;
GS>> HRESULT res=p->QueryInterface(IID_IDispatch, (void**)&pDisp);
Ц>Попробовал, получилось, спасибо. Ц>Правда вместо arrayItems[n].Detach() использовал arrayItems[n].CopyTo(retval); Ц>иначе при последующих обращениях -- Cannot evaluate to an object
Моя просдача. С прямым углом перепутал.
И еще — конструкция с new CComObject<> нужна только если хочешь иметь доступ к С++-методам и членам кокласса. Иначе достаточно обычного
CComPtr<IDispatch> p;
HRESULT res = p.CoCreateInstance(CLSID_ComYcl);