интеллектуальные указатели и COM
| StRiKeR | Новичок | www | 5 дек. 2005 | 19:26 | #0 |
|---|
IDirect3DSurface9 *curSurf;
...
texture->GetSurfaceLevel(0, &curSurf);
можно обустроить через интеллектуальные указатели? чтобы смотрелось симпатично и со 99% защитой от эксепшенов :)
| korak | Постоялец | www | 5 дек. 2005 | 20:03 | #1 |
|---|
boost::shared_ptr с правильным deleter, смотри доку по shared_ptr там как раз есть пример как с COM использовать
| _Winnie | Постоялец | www | 5 дек. 2005 | 21:52 | #3 |
|---|
boost::shared_ptr тут не нужен. dx-объекты уже обладают счетчиком ссылок.
boost::shared_ptr <censured> сложно передавать во всякие Create(void **)-функции.
это основная проблема.
Есть два варианта:
1)использовать родной для dx-объектов CComPtr из ATL.
2)
inline void intrusive_ptr_add_ref(IUnknown *p) { p->AddRef(); } inline void intrusive_ptr_release(IUnknown *p) { p->Release(); } template <class T> struct dx_ptr { typedef boost::intrusive_ptr<T> t; }; //HACK: if you are vomiting on this hack, you can use CComPtr or 'get_pp_t<T> get_pp' below #if 1 template <class T> T **get_pp(boost::intrusive_ptr<T> &ptr) { BOOST_STATIC_ASSERT(sizeof(T*) == sizeof(ptr)); ptr = 0; return reinterpret_cast<T**>(&ptr); } #else template <class T> struct get_pp_t { T *p; boost::intrusive_ptr<T> &dx_ptr; get_pp_t(boost::intrusive_ptr<T> &dx_ptr) :p(0) ,dx_ptr(dx_ptr) { } operator T**() { return &p; } operator void**() { return (void**)&p; } ~get_pp_t() { dx_ptr = boost::intrusive_ptr<T>(p, false); } }; template <class T> get_pp_t<T> get_pp(boost::intrusive_ptr<T> &ptr) { return get_pp_t<T>(ptr); } #endif |
Использование:
dx_ptr<ID3DXBuffer>::t i_byte_code, i_messages; dx_ptr<ID3DXConstantTable>::t i_const_table; std::vector<D3DXMACRO> macroses; create_null_terminated_D3DXMACRO_array(defines, macroses); if(!SUCCEEDED(D3DXCompileShader( source, source_len, ¯oses[0], NULL, "main", target.c_str(), //"vs_2_0", 0, get_pp(i_byte_code), get_pp(i_messages), get_pp(i_const_table)))) {
Если моя левая пятка захочет, заменю dx_ptr<T>::t с intrusive_ptr на CComPtr или что-то своё.
| _Winnie | Постоялец | www | 5 дек. 2005 | 22:11 | #4 |
|---|
А чем отличаются CComPtr и _com_ptr_t, что лучше и правильней?
| Qiller | Постоялец | www | 5 дек. 2005 | 22:58 | #5 |
|---|
Что правильней - мммм, оба они вообщем нормальные... _com_ptr_t автоматом кидает (в смысле исключения) _com_error если вызов метода обломался, CComPtr этого не делает. _com_ptr_t автоматом пытается делать QueryInterface при присвоении другого типа интерфейса (_com_ptr_t<IDispatch> a = (IUnknown *)someObject;).
Так как я ATL просто не пользуюсь и люблю #import, то _com_ptr_t естественный выбор :)
Последняя правка: 5 дек. 2005 22:59
| korak | Постоялец | www | 6 дек. 2005 | 0:44 | #6 |
|---|
Using a shared_ptr to hold a pointer to a COM Object
Background: COM objects have an embedded reference count and two member functions that manipulate it. AddRef() increments the count. Release() decrements the count and destroys itself when the count drops to zero.
It is possible to hold a pointer to a COM object in a shared_ptr:
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
{
p->AddRef();
shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
return pw;
}
Note, however, that shared_ptr copies created from pw will not "register" in the embedded count of the COM object; they will share the single reference created in make_shared_from_COM. Weak pointers created from pw will be invalidated when the last shared_ptr is destroyed, regardless of whether the COM object itself is still alive.
| Аслан | Новичок | www | 18 янв. 2006 | 17:07 | #8 |
|---|
Последняя правка: 24 янв. 2006 15:48
| Аслан | Новичок | www | 18 янв. 2006 | 17:39 | #9 |
|---|
>Что правильней - мммм, оба они вообщем нормальные... _com_ptr_t автоматом
>кидает (в смысле исключения) _com_error если вызов метода обломался, CComPtr
Этого не может быть, потому что не может быть никогда. О самом вызове метода _com_ptr_t ничего не знает, в операторе -> он просто возвращает С-шный указатель. А исключение кинет, если оный указатель нулевой.
/ Форум / Программирование игр / Общее
Для определения, можете ли вы оставлять сообщения, необходимо войти в систему под своим логином.