Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 6
На сайте нет зарегистрированных пользователей

Пользователей: 13,372
новичок: vausoz
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Игра Sokoban на Delphi + Блок схемы
Диплом RSA, ЭЦП, сертификаты, шифрование на C#
Метод половинного деления для нахождения корня уровнения на Turbo Pascal...

Оптимизация QueryInterface



Фактически реализация QueryInterface , показанная ранее в этой главе, очень проста и легко может поддерживаться любым программистом, имеющим хоть некоторое представление о СОМ и C++. Тем не менее, многие среды и каркасы приложений поддерживают реализацию, управляемую данными. Это помогает достичь большей расширяемости и эффективности благодаря уменьшению размера кода. Такие реализации предполагают, что каждый совместимый с СОМ класс предусматривает таблицу, которая отображает каждый поддерживаемый IID на какой-нибудь аспект объекта, используя фиксированные смещения или какие-то другие способы. В сущности, реализация QueryInterface , приведенная ранее в этой главе, строит таблицу, основанную на скомпилированном машинном коде для каждого из последовательных операторов if, а фиксированные смещения вычисляются с использованием оператора staticcast (staticcast просто добавляет смещение базового класса, чтобы найти совместимый с типом указатель vptr).
Чтобы реализовать управляемый таблицей 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(reinterpretcast\ (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 появится в исполняемой программе только один раз, это весьма неплохой компромисс.
Очень легко автоматизировать поддержку СОМ для любого класса C++, основанную на таком табличном управлении, простым использованием С-препроцессора. Следующий фрагмент из заголовочного файла impunk.h определяет QueryInterface , AddRef и Release для объекта, использующего интерфейсные таблицы и расположенного в динамически распределяемой области памяти:
// impunk.h (book-specific header file)
// impunk.h (заголовочный файл, специфический для данной книги)
// AUTOLONG is just a long that constructs to zero
// AUTOLONG – это просто long, с конструктором,
// устанавливающим значение в О
struct AUTOLONG
{
LONG value;
AUTOLONG (void) : value (0) {}
};
#define IMPLEMENTUNKNOWN(ClassName)
\ AUTOLONG mcRef;
\ STDMETHODIMP QueryInterface(REFIID riid, void **ppv){
\ return InterfaceTableQueryInterface(this,
\ GetInterfaceTable(), riid, ppv);
\ }
\ STDMETHODIMP(ULONG) AddRef(void) {
\ return InterlockedIncrement(&mcRef.value);
\ }
\ STDMETHODIMP(ULONG) Release(void) {
\ ULONG res = InterlockedDecrement(&mcRef.value) ;
\ if (res == 0)
\ delete this;
\ return res;
\ }



Настоящий заголовочный файл содержит дополнительные макросы для поддержки объектов, не находящихся в динамически распределяемой области памяти.
Для реализации примера PugCat , уже встречавшегося в этой главе, необходимо всего лишь удалить текущие реализации QueryInterface , AddRef и Release и добавить соответствующие макросы:
class PugCat : public IPug, public ICat
{
protected:
virtual ~PugCat(void);
public: PugCat(void);
// IUnknown methods
// методы IUnknown
IMPLEMENTUNKNOWN (PugCat)
BEGININTERFACETABLE(PugCat)
IMPLEMENTSINTERFACE(IPug)
IMPLEMENTSINTERFACE(IDog)
IMPLEMENTSINTERFACEAS(IAnimal,IDog)
IMPLEMENTSINTERFACE(ICat)
ENDINTERFACETABLE()
// IAnimal methods
// методы IAnimal
STDMETHODIMP Eat(void);
// IDog methods
// методы IDog
STDMETHODIMP Bark(void);
// IPug methods
// методы IPug
STDMETHODIMP Snore(void);
// ICat methods
// методы ICat
STDMETHODIMP IgnoreMaster(void);
};



Когда используются эти макросы препроцессора, для поддержки IUnknown не требуется никакого дополнительного кода. Все, что осталось сделать, это реализовать текущие методы интерфейса, которые делают этот класс уникальным.
Опубликовал Kest July 12 2009 21:40:55 · 0 Комментариев · 5994 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Переработанный пл...
ShadelLabel
Delphi 7 Enterpri...
Калькулятор [Исхо...
index.php + мод ...
TsHintManager
HtmlLerz PRO
ЯЗЫК ПРОГРАММИРОВ...
Crystal Button
Основы программир...
VFW
C# в кратком изло...
WordReport
TelBook
Программирование ...
База предприятий ...
Dynamic Titles дл...
Самоучитель Прогр...
База данных: Книж...
AUTOWEB

Топ загрузок
Приложение Клие... 100774
Delphi 7 Enterp... 97837
Converter AMR<-... 20268
GPSS World Stud... 17014
Borland C++Buil... 14192
Borland Delphi ... 10292
Turbo Pascal fo... 7374
Калькулятор [Ис... 5984
Visual Studio 2... 5207
Microsoft SQL S... 3661
Случайные статьи
Датчики магнитного...
Копирование печатн...
Архитектура станда...
Интересные предлож...
Протокол BiSync от...
UNTRACE (ЗАВЕРШИТЬ...
6.4. Задачи
У типичного руково...
Unexpected end of ...
Оглавление
Виртуальное казино...
ОСНОВНЫЕ РАЗЛИЧИЯ ...
Особенности примен...
Сортировка с помощ...
Каналы Ethernet LA...
Убрать копирайт в ...
Строка -> список
Драйвер ip
Программа содержит...
Битовые поля
13.2. Линейные стр...
Не можете найти об...
Язык С и С ++: фун...
Добавление и измен...
Секреты: принцип р...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?