Анатомия C Run-Time, или Как сделать программу немного меньшего размера
Страница 13. Директива #import и ее ограничения в облегченных проектах


 

Директива #import и ее ограничения в облегченных проектах

Частой причиной появления зависимости от CRT является необдуманное применение директивы #import - расширения Visual C++ для удобства работы с COM-объектами, предоставляющими библиотеки типов. Подробнее о ней можно прочитать в MSDN, а на русском языке - в статье Игоря Ткачева "Использование директивы #import в Visual C++" .

При ее использовании компилятор генерирует описания интерфейсов и, если не указано обратное, создает набор оберточных классов (wrappers) для упрощения работы с указателями на эти интерфейсы. Кроме того, детали реализации COM-объектов скрываются за высокоуровневыми средствами. В число таких деталей входят преобразование [out,retval]-параметров в возвращаемые значения функций, упрощение работы с BSTR-строками, управление сроками жизни объектов, доступ к свойствам и преобразование COM-HRESULT в исключения С++. Но поддержка всех этих приятных "мелочей" реализована с использованием CRT и требует включения стартового кода CRT.

Директива #import, несомненно, полезна для C++-программиста - ведь иначе, не имея описания интерфейсов, пришлось бы извлекать необходимую информацию вручную с помощью утилит типа OleView. Эту директиву можно применять и в проектах, не использующих CRT, но с рядом ограничений. В частности, необходимо подавить создание оберточных классов и трансляцию типов COM в классы-обертки _com_ptr, _com_error, _variant_t и _bstr_t. Вот пример выверенного использования #import, которое не "потянет" за собой половину кода CRT:

#import "file.dll" no_namespace, \
named_guids, no_implementation, \
raw_interfaces_only, raw_dispinterfaces, \
raw_native_types

Иногда при использовании #import можно обойтись "малой кровью". Это возможно, например, если в интерфейсах импортируемой библиотеки типов не используются BSTR- и VARIANT-параметры (вообще-то, достаточно редкий случай). Тогда можно воспользоваться всеми удобствами, предоставляемыми #import, но подавить генерацию исключений C++ при возврате ошибок. Для этого потребуется реализовать функцию

void __stdcall _com_issue_error(HRESULT hr);

Такая возможность определяется в каждом конкретном случае экспериментально. Все же, если вы не используете исключения, лучше отказаться от расширенной помощи директивы #import и обрабатывать HRESULT вручную.

ПРИМЕЧАНИЕ

В составе уже упомянутой библиотеки ATL/AUX есть средство автоматической генерации классов из библиотек типов, которое более пригодно для сверхмалых проектов, чем директива #import.

 
« Предыдущая статья   Следующая статья »