Сущность технологии СОМ. Библиотека программиста
Добавить в закладки К обложке
- Предисловие Чарли Киндела - Страница 1
- Предисловие Грэйди Буча - Страница 4
- От автора - Страница 5
- Благодарности - Страница 7
- От издательства - Страница 9
- Глава 1. СОМ как улучшенный C++ - Страница 10
- Распространение программного обеспечения и язык С++ - Страница 11
- Динамическая компоновка и С++ - Страница 12
- C++ и мобильность - Страница 13
- Инкапсуляция и С++ - Страница 14
- Отделение интерфейса от реализации - Страница 17
- Абстрактные базы как двоичные интерфейсы - Страница 19
- Полиморфизм на этапе выполнения - Страница 23
- Расширяемость объекта - Страница 25
- Управление ресурсами - Страница 28
- Где мы находимся? - Страница 30
- Глава 2. Интерфейсы - Страница 31
- Снова об интерфейсах и реализациях - Страница 32
- IDL - Страница 33
- Методы и их результаты - Страница 35
- Интерфейсы и IDL - Страница 37
- Интерфейс IUnknown - Страница 39
- Управление ресурсами и IUnknown - Страница 42
- Приведение типов и IUnknown - Страница 45
- Реализация IUnknown - Страница 47
- Использование указателей интерфейса СОМ - Страница 50
- Оптимизация QueryInterface - Страница 52
- Типы данных - Страница 55
- Атрибуты и свойства - Страница 61
- Исключения - Страница 62
- Где мы находимся? - Страница 65
- Глава 3. Классы - Страница 66
- Снова об интерфейсе и реализации - Страница 67
- Объекты классов - Страница 69
- Активация - Страница 71
- Использование SCM - Страница 73
- Классы и серверы - Страница 76
- Обобщения - Страница 81
- Оптимизации - Страница 83
- Снова интерфейс и реализация - Страница 86
- Моникеры и композиция - Страница 89
- Моникеры и сохраняемость - Страница 91
- Время жизни сервера - Страница 93
- Классы и IDL - Страница 95
- Эмуляция классов - Страница 97
- Категории компонентов - Страница 98
- Где мы находимся? - Страница 102
- Глава 4. Объекты - Страница 103
- Снова IUnknown - Страница 104
- QueryInterface симметрична - Страница 105
- QueryInterface транзитивна - Страница 106
- QueryInterface рефлективна - Страница 107
- Объекты имеют статический тип - Страница 108
- Единственность и идентификация - Страница 110
- QueryInterface и IUnknown - Страница 111
- Множественные интерфейсы и имена методов - Страница 113
- Динамическая композиция - Страница 118
- Двоичная композиция - Страница 122
- Включение - Страница 128
- Где мы находимся? - Страница 129
- Глава 5. Апартаменты - Страница 130
- Снова интерфейс и реализация - Страница 131
- Объекты, интерфейсы и апартаменты - Страница 134
- Межапартаментный доступ - Страница 136
- Вспомогательные средства для внутрипроцессного маршалинга - Страница 141
- Архитектура стандартного маршалинга - Страница 144
- Реализация интерфейсных маршалеров - Страница 148
- Стандартный маршалинг, потоки и протоколы - Страница 150
- Управление жизненным циклом и маршалинг - Страница 154
- Специальный маршалинг - Страница 159
- Маршалер свободной поточной обработки (FreeThreaded Marshaler) - Страница 162
- Где мы находимся? - Страница 168
- Глава 6. Приложения - Страница 169
- Подводные камни внутрипроцессной активации - Страница 170
- Активация и SCM - Страница 171
- Снова о времени жизни сервера - Страница 174
- Снова о времени жизни сервера - Страница 178
- Идентификаторы приложений - Страница 182
- COM и защита - Страница 185
- Программируемая защита - Страница 191
- Контроль доступа - Страница 196
- Управление маркерами - Страница 200
- Где мы находимся? - Страница 204
- Разное - Страница 205
- Основы указателей - Страница 206
- Указатели и память - Страница 208
- Массивы - Страница 213
- Управление потоками данных - Страница 221
- Динамический вызов в сравнении со статическим - Страница 224
- Двунаправленные интерфейсные контракты - Страница 227
- Совмещение имен в IDL - Страница 233
- Асинхронные методы - Страница 236
- Где мы находимся? - Страница 237
- Проиложение А. Эволюция объектов - Страница 238
- Приложение Б. Избранный код - Страница 242
HRESULT CreateInstance([in] Unknown *pUnkOuter, [in] REFIID riid, [out, iid_is(riid)] void **ppv);
Этот метод (и соответствующие API-функции CoCreateInstanceEx и CoCreateInstance) перегружен с целью поддержки создания автономных (stand-alone ) объектов и агрегатов. Если вызывающий объект передает нулевой указатель и качестве первого параметра CreateInstance (pUnkOuter ), то результирующий объект будет автономной идентификационной единицей самого себя. Если же вызывающий объект передает в качестве первого параметра ненулевой указатель, то результирующий объект будет агрегатом с идентификационной единицей, ссылка на которую содержится в pUnkOuter. В случае агрегации агрегат должен переадресовывать все запросы QueryInterface, AddRef и Release непосредственно и безусловно на pUnkOuter. Это необходимо для обеспечения идентификации объекта.
Имея прототип функции, приведенный выше, класс CarBoat после небольшой модификации будет удовлетворять правилам агрегации:
CarBoat::CarBoat(void) : m_cRef(0)
{
// need to pass identity of self to Create routine
// to notify car object it 1s an aggregate
// нужно передать свою идентификацию подпрограмме
// Create для уведомления объекта car, что он – агрегат
HRESULT hr = CoCreateInstance(CLSID_Car, this, CLSCTX_ALL, IID_IUnknown, (void**)&m_pUnkCar);
assert(SUCCEEDED(hr));
}
Реализация CarBoat QueryInterface просто переадресовывает запрос ICar внутреннему агрегату:
STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv)
{
if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(this);
else if (riid == IID_ICar)
// forward request…
// переадресовываем запрос…
return m_pUnkCar->QueryInterface(riid, ppv);
else if (riid == IID_IBoat)
:
:
:
Теоретически это должно работать, так как агрегат будет всегда переадресовывать любые последующие запросы QueryInterface обратно главному объекту, проводя таким образом идентификацию объекта.
В предыдущем сценарии метод CreateInstance класса Car возвращает внешнему объекту указатель интерфейса, наследующего IUnknown. Если бы этот интерфейсный указатель должен был просто делегировать вызовы функций интерфейсу IUnknown внешнего объекта, то невозможно было бы: 1) уведомить агрегат, что он больше не нужен; 2) запросить интерфейсные указатели при выделении их клиентам главного объекта. На деле результатом приведенной выше реализации QueryInterface будет бесконечный цикл, поскольку внешний объект делегирует функции внутреннему, который делегирует их обратно внешнему.
Для решения этой проблемы необходимо сделать так, чтобы начальный интерфейсный указатель, который возвращается внешнему объекту, не делегировал вызовы реализации IUnknown внешнего объекта. Это означает, что объекты, поддерживающие СОМ– агрегирование, должны иметь две реализации IUnknown. Делегирующая, то есть передающая функции, реализация переадресовывает все запросы QueryInterface, AddRef и Release внешней реализации. Это и есть реализация по умолчанию, на которую ссылаются таблицы vtbl всех объектов, и это именно та версия, которую видят внешние клиенты. Объект должен также иметь неделегирующую реализацию IUnknown, которая выставляется только агрегирующему внешнему объекту.
Имеется несколько возможностей обеспечить две различные реализации IUnknown от одного объекта. Самый прямой путь[1] – это использование композиции и элемента данных для реализации неделегирующих методов IUnknown. Ниже показана реализация Car, поддающаяся агрегации:
class Car : public ICar
{
LONG m_cRef;
IUnknown *m_pUnk0uter;
public: Car(IUnknown *pUnk0uter);
// non-delegating IUnknown methods
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253