Получаем интерфейс: спец. функц., QueryInterface, CoCreate..

Обсуждение вопросов, касающихся указанной технологии.
Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Получаем интерфейс: спец. функц., QueryInterface, CoCreate..

Сообщение Admiralisimys » 22.02.2012 (Ср) 20:03

Салют!
Какой способ получения COM-интерфейса используете вы?
Вопрос теоретического наклона, так как на практике - это несколько способов сделать одно и тоже, но с разной степенью абстракции (от более высоко уровня к низкоуровневому).

Далее в качестве примера возьмём интерфейс IDirectDraw7
Код: Выделить всё
HRESULT hr;
LPDIRECTDRAW7 m_pDD;


1)Специализированная функция (если такая имеется для конкретного интерфейса)
Код: Выделить всё
bool InitGraphics1(GUID *pDDrawGuid)
{
   if(m_pDD)
      return false;
   hr = DirectDrawCreateEx(pDDrawGuid,
                     reinterpret_cast<void **>(&m_pDD),
                     IID_IDirectDraw7, NULL);
   if(FAILED(hr))
      return false;
   return true;
}


2)Получения интерфейса через запрос в методе QueryInterface уже полученного интерфейса
Код: Выделить всё
bool InitGraphics2(GUID *pDDrawGuid)
{
   if(m_pDD)
      return false;
   LPDIRECTDRAW legacyDD = NULL;

   hr = DirectDrawCreate(NULL, &legacyDD, NULL);
   if(FAILED(hr))
      return false;
   
   if(legacyDD)
   {
      hr = legacyDD ->
         QueryInterface(IID_IDirectDraw7,
                     reinterpret_cast<void **>(&m_pDD));
      legacyDD -> Release();
   }
   legacyDD = NULL;

   if(FAILED(hr))
      return false;

   return true;
}

Так как все COM интерфейсы наследники абстрактного IUnknown, у которого есть метод QueryInterface, через который можно получить любой интерфейс. А DirectDrawCreate может получить интерфейс до версии IDirectDraw7, но он здесь в качестве примера.

3)Получение через функцию общего назначения CoCreateInstance, с подготовкой по использованию COM.
Код: Выделить всё
bool InitGraphics3(GUID *pDDrawGuid)
{
   if(m_pDD)
      return false;
   hr = CoInitialize(NULL);
   if(FAILED(hr))
      return false;

   //LaMothe use only CLSID_DirectDraw without 7. Why?
   hr = CoCreateInstance(CLSID_DirectDraw,
            NULL, CLSCTX_ALL, IID_IDirectDraw7,
            reinterpret_cast<void **>(&m_pDD));

   CoUninitialize();

   if(FAILED(hr))
      return false;

   hr = m_pDD -> Initialize(pDDrawGuid);

   if(FAILED(hr))
      return false;

   return true;
}

Собственно последний способ описан Андре Ламот и назван как рекомендованный Microsoft(возможно это касается только IDirectDraw7).

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Получаем интерфейс: спец. функц., QueryInterface, CoCrea

Сообщение Хакер » 23.02.2012 (Чт) 7:07

Admiralisimys писал(а):Так как все COM интерфейсы наследники абстрактного IUnknown

IUnknown вовсе не абстрактный.

По своей сути весь вопрос бредов, потому что:
Admiralisimys писал(а):то несколько способов сделать одно и тоже

— неправда.

1) Специальные функции, как ты называешь, это COM-библиотеки, не являющиеся при этом ActiveX-библиотеками. Их прототип, их параметры, их поведение нигде не регламентировано, разработчики вольны извращаться как им вздумается. И если в одном частном случае (DirectX) разработчики вложили в поведение такой функции ещё и вызова QueryInterface... Что-ж. Они вложили, другие не вложили. В этом случае можешь пользоваться, в другом такой возможности просто не будет.

Самое главное, что функция не столько возращает интерфейс (хотя, безусловно, в конечном счёте она как не крути возвращает интерфейс), сколько либо создаёт новый объект, либо, при singleton-подходе, возвращает ссылку на уже живущий объект. При этом, конечно, кто-то спросит, ссылку на какой интерфейс нового/существующего объекта вернуть, а кто-то не спросит, и вернёт ссылку на конкретный интерфейс нового / уже существующего объекта.

2) Собственно, это основной метод в COM получить от одного интерфейса объекта любой другой интерфейс объекта. В чём вопрос? Стоит ли её вызывать? Да не только стоит, а просто и не получится по другому.

3) А CoCreateInstance — это уже единый, стандартизованный, рекомендованный, «инновационный» механизм создания объекта из библиотек теперь уже из ActiveX-серверов (которыми могут быть не только DLL, но и EXE), и лежать они теперь могут не только на той же машине, где создающая сторона, но и на другой, и объект и его создатель могут быть в разных апартаментах.
Это тоже никакой не способ запроса интерфейса, а способ создание нового объекта (причём обязательно экземпляра класса).
Если первый метод был супер-неконкретным, вплане того, что мог возвращать экземпляр уже существующего объекта, а объект мог вообще быть не-классовым (существующим в единственном экземпляре не фактически, а по своей конструкции), то здесь обязательно должен быть класс (и как следствие — обязательно должна быть фабрика для этого класса), и должен всегда создаваться (и возвращаться) новый экземпляр. То, что при всём при этом вызывающей стороне дали ещё и возможность указать, какой интерфейс вернуть — это просто маленькая плюшечка.

_____

Итак, ты написал три совершенно разных вещи.
1) Экспортируемые библиотеками функции (как явление), в частности, возвращающие ссылки на существующие/новые экземпляры объектов. Это касается только тех DLL-библиотек, у которых такие функции есть.

2) Одна из базовых возможностей COM/

3) Единый способ создания новых экземпляров классов, который поддерживается ActiveX-серверами (DLL-шками, но не любыми, а только теми, которые являются ActiveX-серверами или EXE-шниками, но не всеми, а только теми, которые являются ActiveX-серверами).

______

Это всё равно, что спрашивать:
Какой вариант мне выбрать?
1) Пойти работать грузчиком.
2) Принимать пищу каждый день
3) Устроиться на работу композитором.

Очевидно, что без второго варианта вообще не прожить, а выбор между третьим и первым определяется по способности человека выполнять конкретную физ. / творческую работу. Это не две (и не три) равные альтернативы.

Тот факт, что DirectX является одновременно и классической COM-библиотекой, и ActiveX-серверов, это просто частный случай. Кто угодно может сделать что-то такое же, но тем не менее, это большая редкость.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: Получаем интерфейс: спец. функц., QueryInterface, CoCrea

Сообщение Admiralisimys » 23.02.2012 (Чт) 23:38

А как тогда понять?
Код: Выделить всё
//Хоть так
IUnknown iunk;
//хоть так
IUnknown *iunk = new IUnknown();
//все равно - error C2259: 'IUnknown' : cannot instantiate abstract class

Во втором примере первоначально и планировал его использовать, как носителя QueryInterface, но ведь не дают.
Или что ты имеешь ввиду под «вовсе не абстрактный»? Что в объявленный ранее объект ссылку можно поместить реальный объект наследственного класса?

Самое главное, что поставив этот вопрос, я получил ответ, расставляющий для меня точки над «i».
Спасибо!

Для всех этих Init’ов был написан лишь один общий release
Код: Выделить всё
void release()
{
   if(m_pDD)
      m_pDD -> Release();
   m_pDD = NULL;
}

Я прав, или для каждой из приведённых функций нужна своя кастомизация?

Насчёт фабрик, то в DirectX 10.1 для некоторых интерфейсов их экспортируемые функции прямо так и называют, например
Код: Выделить всё
HRESULT hr;
ID2D1Factory *pD2DFactory;
//...
bool InitDirect2D_Variant1()
{
   if(pD2DFactory)
      return false;
   hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);

   if(FAILED(hr))
      return false;
   return true;
}

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Получаем интерфейс: спец. функц., QueryInterface, CoCrea

Сообщение Хакер » 23.02.2012 (Чт) 23:49

Admiralisimys писал(а):А как тогда понять?

Так ведь бред собачий — так и понять. Ты пытаешься создать экземпляр С++-шного класса IUnknown. Это полный бред. Во-первых, в COM есть классы, а есть интерфейсы, это два ортогональных понятия. В С++ интерфейсов нет в принципе, их вместо них используются С++-классы.

В любом случае, если после new стоит идентификатор, начинающийся на «I», то эта строчка кода — чушь, и не важно, IUnknown там (как у тебя), или IShellFolder.


В общем, судя по топикам, COM ты понимаешь плохо, и иметь дело с COM из С++ для тебя — затея из худших. Делай на VB6. Он по крайней менее не даст «выстрелить себе в ногу».
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: Получаем интерфейс: спец. функц., QueryInterface, CoCrea

Сообщение Admiralisimys » 24.02.2012 (Пт) 0:18

:oops:
Спасибо и на этом. :D

Так ведь Microsoft по своим последним COM компонентам даёт сопроводительные примеры на С++, по этому когда что-то не ясно привожу код именно на нём. :roll:

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Получаем интерфейс: спец. функц., QueryInterface, CoCrea

Сообщение Хакер » 24.02.2012 (Пт) 10:13

Все так делают, ибо это стандарт для приведения примеров.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в OLE / COM / ActiveX

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

    TopList