Навигация
Главная
Поиск
Форум
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
Реклама
Сейчас на сайте
Гостей: 24
Пользователь: Barmaleika

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

Обработка задач на ЭВМ на GPSS + Пояснительная записка
Расчет обратной матрицы на Delphi + Пояснительная записка
Принадлежит ли точка пересечению двух окружностей на 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 Комментариев · 5968 Прочтений · Для печати

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


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



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

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

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

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

Пароль



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

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

Случайные загрузки
Род Стивенс. Delp...
Программирование ...
Добавление к ссы...
FatScrollbar
IPAddresseEdit
Calendar
MP3 Архив v.2.0
Приложение Клиент...
CaptionButton
Win-Prolog 3.618
PHP: Полезные приемы
Разработка клиент...
Text3D
Encrypt Decrypt
Сапёр
Crypt32
Библия для програ...
SendSMS для PHP-F...
Image Browser [Ис...
Запрет гостям ск...

Топ загрузок
Приложение Клие... 100772
Delphi 7 Enterp... 97809
Converter AMR<-... 20261
GPSS World Stud... 17014
Borland C++Buil... 14189
Borland Delphi ... 10267
Turbo Pascal fo... 7372
Калькулятор [Ис... 5972
Visual Studio 2... 5206
Microsoft SQL S... 3661
Случайные статьи
true
Рекурсивное вычисл...
Осторожное резонан...
Работа с избранным...
Моделирование и си...
Функции ввода-выво...
REALLOCATE (ПЕРЕРА...
7.4. Справочник ...
Как зарегистрирова...
Все о языках-прогр...
Новый вид панели F...
Error in Initial c...
Структуры данных н...
Процедура GETMEM. ...
Есть много других ...
Металлические дета...
Фильтрация таблиц ...
Шинная топология ЛВС
Продолжительность ...
Перевозки из Китая
В какую объединенн...
РЕЖИМ "ПОПОЛНЕНИЕ ...
если участник безо...
Вмешательство в пр...
Установка съемной ...
Статистика



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


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