Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Программирование -> C/C++ -> Сущность технологии COM


Использование указателей интерфейса СОМ

Программисты C++ должны использовать методы IUnknown явно, потому что перевод модели СОМ на язык C++ не предусматривает использования среды поддержки выполнения (runtime layer) между кодом клиента и кодом объекта. Поэтому IUnknown можно рассматривать просто как набор обещаний, которые все программисты СОМ дают друг другу. Это дает преимущество программистам C++, так как C++ может создавать код, который потенциально более эффективен, чем языки, которые требуют такого динамического слоя при работе с СОМ.

При работе на Visual Basic и Java, в отличие от C++, программисты никогда не видят QueryInterface, AddRef или Release. Для этих двух языков детали IUnknown надежно скрыты за поддерживающей эти языки виртуальной машиной. На Java QueryInterface просто отображается в приведение типа:

public void TryToSnoreAndIgnore(Object obj) { 
    IPug pug; 
    try { 
       pug = (IPug)obj; 
       // VM calls QueryInterface 
       // VM вызывает QueryInterface 
       pug.Snore(); 
    } catch (Throwable ex) { 
       // ignore method or QI failures 
       // игнорируем сбой метода или QI 
} 

ICat cat; 

try { 
    cat = (ICat)obj; 
    // VM calls QueryInterface 
    // VM вызывает QueryInterface 
    cat.IgnoreMaster(); 
} catch (Throwable ex) { 
    // ignore method or QI failures 
    // игнорируется сбой метода или QI 
    } 
} 

Visual Basic не требует от клиентов приведения типов. Вместо этого, когда указатель интерфейса присваивается переменной неподходящего типа, виртуальная машина (VM) Visual Basic молча вызывает QueryInterface от имени клиента:

Sub TryToSnoreAndIgnore(obj as Object) 
On Error Resume Next 
' ignore errors 
' игнорируем ошибки 
Dim pug as IPug 
Set pug = obj 
' VM calls QueryInterface 
' VM вызывает QueryInterface 
If Not (pug is Nothing) Then 
  pug.Snore 
End if 
Dim cat as ICat 
Set cat = obj 
' VM calls QueryInterface 
' VM вызывает QueryInterface 
If Not (cat is Nothing) Then 
  cat.IgnoreMaster 
End if End Sub 

Обе виртуальные машины, как Java, так и Visual Basic, выбросят при сбое QueryInterface исключения. В обеих средах виртуальная машина автоматически преобразует языковую концепцию живучести переменной в явные вызовы AddRef и Release, избавляя клиента и от этой подробности.

Одна методика, потенциально способная упростить использование в СОМ интерфейсных указателей из C++, состоит в том, чтобы скрыть их в классе интеллектуальных указателей. Это устраняет необходимость необработанных (raw) вызовов методов IUnknown. В идеале интеллектуальный указатель СОМ будет:

  1. Корректно обрабатывать каждый вызов Add/Release во время присваивания.
  2. Автоматически уничтожать интерфейс в деструкторе, что снижает возможность утечки ресурса и повышает безопасность (надежность) исключений.
  3. Использует систему типов C++ для упрощения вызовов QueryInterface.
  4. Прозрачным образом (незаметно для пользователя или программы) замещает необработанные интерфейсные указатели в существующем коде без компрометации правильности программы.

Последний пункт представляет собой чрезвычайно серьезную проблему. Интернет забит интеллектуальными СОМ-указателями, которые проделывают прозрачную замену обычных указателей, но при этом вводят столько же скрытых ошибок, сколько претендуют устранить. Visual C++ 5.0, например, фактически действует с тремя такими указателями (один на MSC, другой на ATL, а третий для поддержки Direct-to-COM), которые очень просто использовать как правильно, так и неправильно. В сентябрьском 1995 года и в февральском 1996 года выпусках "C++ Report" опубликованы две статьи, где на примерах показаны различные подводные камни при использовании интеллектуальных указателей1. Исходный код, который приводится в данной книге, содержит интеллектуальный СОМ-указатель, созданный в процессе написания этих двух статей. В нем делается попытка учесть общие ошибки, случающиеся как в простых, так и в интеллектуальных указателях СОМ. Класс интеллектуальных указателей, SmartInterface, имеет два шаблонных (template) параметра: тип интерфейса в C++ и указатель на соответствующий IID. Все обращения к методам IUnknown скрыты путем перегрузки операторов:

#include "smartif.h" 
void TryToSnoreAndIgnore(/* [in] */ IUnknown *pUnk) 
{ 
      // copy constructor calls QueryInterface 
      // конструктор копирования вызывает QueryInterface 
    SmartInterface<IPug, &IID_IPug> pPug = pUnk; 
    if (pPug) 
      // typecast operator returns null-ness 
      // оператор приведения типа возвращает нуль 
        pPug->Snore(); 
      // operator-> returns safe raw ptr 
      // оператор -> возвращает прямой указатель 
      // copy constructor calls QueryInterface 
      // конструктор копирования вызывает QueryInterface 
    SmartInterface<ICat, &IID_ICat> pCat = pUnk; 
    if (pCat) 
      // typecast operator returns null-ness 
      // оператор приведения типа возвращает нуль 
        pCat->IgnoreMaster(); 
      // operator-> returns safe raw ptr 
      // оператор -> возвращает прямой указатель 
      // destructors release held pointers on leaving scope 
      // деструкторы освобождают удерживаемые указатели при 
      // выходе из области действия 
} 

Интеллектуальные указатели выглядят очень привлекательными на первый взгляд, но могут оказаться очень опасными, так как погружают программиста в дремотное состояние; будто бы ничего страшного, относящегося к СОМ, произойти не может. Интеллектуальные указатели действительно решают реальные проблемы, особенно связанные с исключениями; однако при неосторожном употреблении они могут внести столько же дефектов, сколько они предотвращают. Например, многие интеллектуальные указатели позволяют вызывать любой метод интерфейса через оператор интеллектуального указателя ->. К сожалению, это позволяет клиенту вызывать Release с помощью этого оператора-стрелки без сообщения базовому интеллектуальному указателю о том, что его автоматический вызов Release в его деструкторе теперь является излишним и недопустимым.


1 Эти статьи можно найти на сайтах http:/www.develop.com/dbox/cxx/InterfacePtr.htm и http://www.develop.com/dbox/cxx/SmartPtr.htm.

Оптимизация QueryInterface
Типы данных
Атрибуты и свойства
Исключения
Где мы находимся?

 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.