Смысл вопроса вот в чем:
Надо взять IEnumUnknown из СОМ-объекта в функции класса, в котором этот объект создается.
Думается, что надо из IEnumUnknown взять IUnknown, передать его через вариант, затем на
стороне функции класса взять этот IUnknown, а из него получить IEnumUnknown.
Привожу кусочек кода, как я это делаю:
//////////////////////////////////////////////
// в своем интерфейсе:
Class IMyEnum : public IEnumUnknown
{
....
}
// собственно класс, описывающий интерфейс
CMyInter
{
IMyEnum m_IMyEnum;
}
STDMETHODIMP CMyInter::get_ToolProperty(long indProp, VARIANT *pVal)
{
IUnknown* pUnk = NULL;
long rc = 0;
HRESULT hRes;
switch(indTool)
{
case 0:
if (FAILED(hRes = m_IMyEnum.QueryInterface(IID_IUnknown, (void**)&pUnk)))
return S_FALSE;
pVal->vt = VT_UNKNOWN;
pVal->punkVal = pUnk;
break;
}
if(pUnk)
{
pUnk->Release(); // ??? не знаю еще, вызывать или нет
pUnk = NULL;
}
return S_OK;
}
//////////////////////////////////////////////
// в приложении пишу:
class Temp
{
void Get();
IEnumUnknown* m_pIEU;
CComQIPtr<IMyInter, &IID_IMyInter> m_pIMy;
...
}
void CTemp::Get()
{
...
VARIANT vt;
if(FAILED(m_pIMy->get_ToolProperty(0, &vt)))
return;
if(FAILED(vt.punkVal->QueryInterface(IID_IEnumUnknown, (void**)&m_pIEU)))
return;
vt.punkVal->Release();
...
}
Внимание, Господа Знатоки, вопрос:
Правильно ли я делаю?
Спасибо за внимание.
Здравствуйте LeonGorbachov, Вы писали:
LG>Смысл вопроса вот в чем:
LG>Надо взять IEnumUnknown из СОМ-объекта в функции класса, в котором этот объект создается.
LG>Думается, что надо из IEnumUnknown взять IUnknown, передать его через вариант, затем на
LG>стороне функции класса взять этот IUnknown, а из него получить IEnumUnknown.
LG>STDMETHODIMP CMyInter::get_ToolProperty(long indProp, VARIANT *pVal)
LG>{
LG> IUnknown* pUnk = NULL;
LG> long rc = 0;
LG> HRESULT hRes;
LG> switch(indTool)
LG> {
LG> case 0:
LG> if (FAILED(hRes = m_IMyEnum.QueryInterface(IID_IUnknown, (void**)&pUnk)))
LG> return S_FALSE;
LG> pVal->vt = VT_UNKNOWN;
LG> pVal->punkVal = pUnk;
LG> break;
LG> }
LG>// if(pUnk)
LG>// {
LG>// pUnk->Release(); // ??? не знаю еще, вызывать или нет
LG>// pUnk = NULL;
LG>// }
LG> return S_OK;
LG>}
Можно использовать упрощенную конструкцию, без использования pUnk.
pVal->vt = VT_UNKNOWN; // VT_UNKNOWN используется при передачи vtable интерфейса
// иначе VT_DISPATCH
if (FAILED(hRes = m_IMyEnum.QueryInterface(IID_IUnknown, (void**)&pVal->punkVal))) // или IID_IEnumUnknown
return S_FALSE;
break;
LG>//////////////////////////////////////////////
LG>// в приложении пишу:
LG>void CTemp::Get()
LG>{
LG>...
LG> VARIANT vt;
LG> if(FAILED(m_pIMy->get_ToolProperty(0, &vt)))
LG> return;
LG> if(FAILED(vt.punkVal->QueryInterface(IID_IEnumUnknown, (void**)&m_pIEU)))
LG> return;
LG> vt.punkVal->Release();
LG>...
LG>}
LG>
А вот запрашивать тот интерфейс, который тебе нужен, ОБЯЗАТЕЛЬНО, даже если ты знаешь, что возвращается именно тот интерфейс, который тебе нужен. Это в случае VARIANT-ов. Если функция возвращает интерфейс Ixxx, то и в этом случае ЖЕЛАТЕЛЬНО запросить твой интерфейс.
А вот vt.punkVal->Release(); нужно и в случае ошибки в vt.punkVal->QueryInterface !!!
LG>Внимание, Господа Знатоки, вопрос: Правильно ли я делаю?
В общем-то, правильно.