класс, как аргумент метода
От: nalex  
Дата: 22.12.03 10:02
Оценка:
Hi!

При написании своего первого COM сервера столкнулся со следующей проблемой:
Есть класс Class1, у которого есть метод
getClass2( /*out*/ IUnknown** p )
.
Как правильно создать объект class2 и передать его адрес для последующего использования клиентом?
Re: класс, как аргумент метода
От: kiamor  
Дата: 22.12.03 10:21
Оценка:
Здравствуйте, nalex.

Ну ежели ты хочешь, чтобы клиент мог создавать этот самый class2 только через один из методов
твоего интерфейса, то всё правильно. Лепи в IDL атрибут noncreateble к коклассу и всех делов.
Создавать и возвращать сам будешь. Ну а удаление объекта через Release. Как обычно.
Re[2]: класс, как аргумент метода
От: nalex  
Дата: 22.12.03 13:23
Оценка:
Здравствуйте, kiamor, Вы писали:

K>Ну ежели ты хочешь, чтобы клиент мог создавать этот самый class2 только через один из методов

K>твоего интерфейса
Да, именно это я пытаюсь сделать

K>Лепи в IDL атрибут noncreateble к коклассу и всех делов.

Я неправильно объяснил, проблема у меня именно в создании и возвращении указателя

Сейчас пытался сделать так:
Class1::connect(
/*[in]*/ BSTR User,
/*[in]*/ BSTR Pass,
/*[out]*/ IUnknown** pSrv)
{
HRESULT hr = S_OK;
CComObject<Class2> * pClass2 = NULL;
pSrv = NULL;
pClass2 = new CComObject<pClass2>;
hr = pClass2->QueryInterface( IID_IGrandSmetaSrv, reinterpret_cast<void **>(&pSrv) ) ;
if ( FAILED(hr) )
delete pClass2;
return hr;
}

В клиентской программе при выполнении этого метода все проходит отлично. Но при попытке как-то использовать объект pSrv
получаю ошибку 80004003 "Неправильный указатель".

Как правильно должен работать этот метод?
Re[3]: Указатель pSrv
От: Vi2 Удмуртия http://www.adem.ru
Дата: 22.12.03 13:34
Оценка:
Здравствуйте, nalex, Вы писали:

Нужна * перед pSrv
N>    * pSrv = NULL;

Не нужен & перед pSrv
N>    hr = pClass2->QueryInterface( IID_IGrandSmetaSrv, reinterpret_cast<void **>(pSrv) ) ;
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Указатель pSrv
От: nalex  
Дата: 22.12.03 13:58
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, nalex, Вы писали:


Vi2>Нужна * перед pSrv

Vi2>
N>>    * pSrv = NULL;
Vi2>

Поставил, без изменений.

Vi2>Не нужен & перед pSrv

Vi2>
N>>    hr = pClass2->QueryInterface( IID_IGrandSmetaSrv, reinterpret_cast<void **>(pSrv) ) ;
Vi2>

Она была, я случайно ее пропустил
Re[5]: Указатель pSrv
От: Vi2 Удмуртия http://www.adem.ru
Дата: 22.12.03 14:41
Оценка:
Здравствуйте, nalex, Вы писали:

N>Она была, я случайно ее пропустил

Кто была? И как можно пропустить наличие символа &?

Class1::connect(/*[in]*/ BSTR User, /*[in]*/ BSTR Pass, /*[out]*/ IUnknown** pSrv)
{
HRESULT hr = S_OK;
CComObject<Class2> * pClass2 = NULL;

pSrv = NULL; //Vi2 - нужно: * pSrv = ...

pClass2 = new CComObject<Class2>;

hr = pClass2->QueryInterface( IID_IGrandSmetaSrv, reinterpret_cast<void **>(&pSrv) ) ; //Vi2 - нужно: (pSrv)

if ( FAILED(hr) ) 
delete pClass2;
return hr;
}
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Указатель pSrv
От: Thanatos Украина  
Дата: 22.12.03 14:58
Оценка: +1
Здравствуйте, Vi2, Вы писали:

Vi2>Class1::connect(/*[in]*/ BSTR User, /*[in]*/ BSTR Pass, /*[out]*/ IUnknown** pSrv)

Vi2>{
Vi2>HRESULT hr = S_OK;
Vi2>CComObject<Class2> * pClass2 = NULL;

Vi2>pSrv = NULL; //Vi2 — нужно: * pSrv = ...


Vi2>pClass2 = new CComObject<Class2>;


Vi2>hr = pClass2->QueryInterface( IID_IGrandSmetaSrv, reinterpret_cast<void **>(&pSrv) ) ; //Vi2 — нужно: (pSrv)


Можно, но плохо, — (*pSrv)->AddRef().
Лучше — CComObject<Class2>::CreateInstance(pSrv) вместо pClass2 = new CComObject<Class2>;
А если не нужен доступ к тем переменным Class2, которые не вынесены в интерфейс, то ещё лучше — CoCreateInstance(...).

Vi2>if ( FAILED(hr) )

Vi2>delete pClass2;
Vi2>return hr;
Vi2>}
Лучший дар, который мы получили от природы и который лишает нас всякого права жаловаться – это возможность сбежать. /М.Монтень/
Re[7]: Указатель pSrv
От: Thanatos Украина  
Дата: 22.12.03 15:01
Оценка:
Здравствуйте, Thanatos, Вы писали:

Ой... предыдущий пост, конечно же, 2nalex...
Лучший дар, который мы получили от природы и который лишает нас всякого права жаловаться – это возможность сбежать. /М.Монтень/
Re[6]: Указатель pSrv
От: George Seryakov Россия  
Дата: 24.12.03 02:44
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>
Vi2>Class1::connect(/*[in]*/ BSTR User, /*[in]*/ BSTR Pass, /*[out]*/ IUnknown** pSrv)
Vi2>{
Vi2>HRESULT hr = S_OK;
Vi2>CComObject<Class2> * pClass2 = NULL;

Vi2>pSrv = NULL; //Vi2 - нужно: * pSrv = ...

Vi2>pClass2 = new CComObject<Class2>;

Это создает кокласс. Кокласс создается с нулевым счетчиком ссылок.

Vi2>hr = pClass2->QueryInterface( IID_IGrandSmetaSrv, reinterpret_cast<void **>(&pSrv) ) ; //Vi2 - нужно: (pSrv)

Вызов QI увеличивает счетчик ссылок.

Vi2>if ( FAILED(hr) ) 
Vi2>delete pClass2;

Кокласс удаляется невзирая на его счетчик ссылок.

Vi2>return hr;
Vi2>}
Vi2>


То есть — не удалять кокласс, уповая, что, когда ты освободишь объект в клиенте (обнулишь счетчик) он удалится сам собой, либо (как указал Thanatos) вызывать CCI (счетчик -> 1), затем QI (счетчик -> 2), а затем Release, который ничего не зарелизит (счетчик -> 1), но симметрия кода будет соблюдена, а вместе с ней и корректность.
GS
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.