Чтение онлайн

на главную - закладки

Жанры

Сущность технологии СОМ. Библиотека программиста
Шрифт:

Чтобы реализовать управляемый таблицей QueryInterface, необходимо сначала определить, что эта таблица будет содержать. Как минимум, каждый элемент таблицы должен содержать указатель на IID и некое дополнительное состояние, которое позволит реализации найти указатель vptr объекта для запрошенного интерфейса. Хранение указателя функции в каждом элементе таблицы придаст этому способу максимальную гибкость, так как это даст возможность добавлять новые методики поиска интерфейсов к обычному вычислению смещения, которое используется для приведения к

базовому классу. Исходный код в приложении к данной книге содержит заголовочный файл inttable.h , который определяет элементы таблицы интерфейсов следующим образом:

// inttable.h (book-specific header file)

// inttable.h (заголовочный файл, специфический для этой книги)

// typedef for extensibility function

// typedef для функции расширяемости

typedef HRESULT (*INTERFACEFINDER) (void *pThis, DWORD dwData, REFIID riid, void **ppv);

// pseudo-function to indicate entry is just offset

// псевдофункция для индикации того, что запись просто

// является смещением

#define ENTRYISOFFSET INTERFACEFINDER(-1)

// basic table layout // представление базовой таблицы

typedef struct INTERFACEENTRY

{

const IID * pIID;

// the IID to match

// соответствующий IID

INTERFACEFINDER pfnFinder;

// функция finder DWORD dwData;

// offset/aux data

// данные по offset/aux

} INTERFACEENTRY;

Заголовочный файл также содержит следующие макросы для создания интерфейсных таблиц внутри определения класса:

// Inttable.h (book-specific header file)

// Inttable.h (заголовочный файл, специфический для данной книги)

#define BASEOFFSET(ClassName, BaseName) \ (DWORD(staticcast<BaseName*>(reinterpretcast\ <ClassName*>(0x10000000))) – 0х10000000)

#define BEGININTERFACETABLE(ClassName) \ typedef ClassName ITCls;\ const INTERFACEENTRY *GetInterfaceTable(void) {\ static const INTERFACEENTRY table [] = {\

#define IMPLEMENTSINTERFACE(Itf) \ {&IID##Itf,ENTRYISOFFSET,BASEOFFSET(ITCls,Itf)},

#define IMPLEMENTSINTERFACEAS(req, Itf) \ {&IID##req,ENTRYISOFFSET, BASEOFFSET(ITCls, Itf)},

#define ENDINTERFACETABLE \ { 0, 0, 0 } }; return table; }

Все, что требуется, – это стандартная функция, которая может анализировать интерфейсную таблицу в ответ на запрос QueryInterface.

Такая функция содержится в файле Inttable.h:

// inttable.cpp (book-specific source file)

// inttable.h (заголовочный файл, специфический для данной книги)

HRESULT InterfaceTableQueryInterface(void *pThis, const INTERFACEENTRY *pTable, REFIID riid, void **ppv)

{

if (InlineIsEqualGUID(riid, IIDIUnknown))

{

// first entry must be an offset

// первый элемент должен быть смещением

*ppv = (char*)pThis + pTable->dwData;

((Unknown*) (*ppv))->AddRef ;

// A2

return SOK;

} else

{

HRESULT hr = ENOINTERFACE;

while (pTable->pfnFinder)

{

// null fn ptr == EOT

if (!pTable->pIID || InlineIsEqualGUID(riid,*pTable->pIID))

{

if (pTable->pfnFinder == ENTRYISOFFSET)

{

*ppv = (char*)pThis + pTable->dwData;

((IUnknown*)(*ppv))->AddRef;

// A2

hr = SOK;

break;

} else

{

hr = pTable->pfnFinder(pThis, pTable->dwData, riid, ppv);

if (hr == SOK) break;

}

}

pTable++;

}

if (hr!= SOK)

*ppv = 0;

return hr;

}

}

Получив указатель на запрошенный объект, InterfaceTableQueryInterface сканирует таблицу в поисках элемента, соответствующего запрошенному IID, и либо добавляет соответствующее смещение, либо вызывает соответствующую функцию. Приведенный выше код использует усовершенствованную версию IsEqualGUID, которая генерирует несколько больший код, но результаты по скорости примерно на 20-30 процентов превышают данные по существующей реализации, которая не управляется таблицей. Поскольку код для InterfaceTableQueryInterface появится в исполняемой программе только один раз, это весьма неплохой компромисс.

Поделиться:
Популярные книги

1941: Время кровавых псов

Золотько Александр Карлович
1. Всеволод Залесский
Приключения:
исторические приключения
6.36
рейтинг книги
1941: Время кровавых псов

Весь цикл «Десантник на престоле». Шесть книг

Ланцов Михаил Алексеевич
Десантник на престоле
Фантастика:
альтернативная история
8.38
рейтинг книги
Весь цикл «Десантник на престоле». Шесть книг

Попаданка 2

Ахминеева Нина
2. Двойная звезда
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Попаданка 2

Кротовский, не начинайте

Парсиев Дмитрий
2. РОС: Изнанка Империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Кротовский, не начинайте

Вечный. Книга VI

Рокотов Алексей
6. Вечный
Фантастика:
рпг
фэнтези
5.00
рейтинг книги
Вечный. Книга VI

Локки 5. Потомок бога

Решетов Евгений Валерьевич
5. Локки
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Локки 5. Потомок бога

Миф об идеальном мужчине

Устинова Татьяна Витальевна
Детективы:
прочие детективы
9.23
рейтинг книги
Миф об идеальном мужчине

Кровь на эполетах

Дроздов Анатолий Федорович
3. Штуцер и тесак
Фантастика:
альтернативная история
7.60
рейтинг книги
Кровь на эполетах

Темный Лекарь 6

Токсик Саша
6. Темный Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Темный Лекарь 6

Опасная любовь командора

Муратова Ульяна
1. Проклятые луной
Фантастика:
фэнтези
5.00
рейтинг книги
Опасная любовь командора

Как я строил магическую империю 4

Зубов Константин
4. Как я строил магическую империю
Фантастика:
боевая фантастика
постапокалипсис
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 4

Титан империи 8

Артемов Александр Александрович
8. Титан Империи
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Титан империи 8

На прицеле

Кронос Александр
6. Лэрн
Фантастика:
фэнтези
боевая фантастика
стимпанк
5.00
рейтинг книги
На прицеле

Вечный. Книга III

Рокотов Алексей
3. Вечный
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга III