Какие классы интеллектуального указателя COM использовать?
Меня смущает выбор классов интеллектуальных указателей COM для программирования на С++:
Там три четыре, о которых я знаю:
-
CCOMPtr
от ATL
-
_com_ptr_t
из классов поддержки MS Com
-
TComInterface
(потому что я использую С++ Builder 2009)
-
CCOMQIPtr
, (который я ранее забыл)
Я читал о различиях в обработке ошибок и исключений из первых двух, но TComInterface
кажется полностью недокументированным. Как первые два, кажется, имеют gotchas или "неожиданное" поведение, из того, что я могу найти.
В идеале, мне бы хотелось что-то, что чистым и современным С++, но boost::com
не существует, насколько я знаю...
Мне нужно управлять приложением от другого поставщика. Они предоставляют COM-интерфейс через файл TLB.
Ответы
Ответ 1
Если вы используете материал импорта библиотеки типов, он будет генерировать код на основе _com_ptr_t
и связанных классов поддержки COM. Идем дальше и используем их, если вы просто используете материал из этих библиотек.
Если вы пишете код на основе ATL, используйте CCOMPtr
и другие классы на основе ATL.
Вещи могут стать уродливыми, если вам нужно смешивать и сопоставлять оба типа, но вы, вероятно, должны просто устроиться с ними и использовать то, что имеет наибольший смысл для того, что вы делаете в то время.
Хорошо, что у вас есть источник всех этих вещей, поэтому вам не нужно полагаться только на документацию (которая не проявляла особой осторожности, так как появился .NET).
Ответ 2
Поскольку вы просите "чистый и современный" стиль С++ и даете импульс в качестве примера, я добавлю еще два: std/boost::shared_ptr
и boost::intrusive_ptr
. По-видимому, intrusive_ptr является более естественным выбором, поскольку объекты COM имеют встроенный механизм подсчета ссылок. shared_ptr работает так же хорошо, вам нужно использовать только пользовательский удаляющий вызов, который вызывает IUnknown::Release()
, и небольшую функцию генератора объектов, которая выполняет IUnknown::AddRef()
и возвращает интеллектуальный указатель.
Я обычно иду с intrusive_ptr
, поэтому я объясню это более подробно. Во-первых, конечно, intrusive_ptr_add_ref и intrusive_ptr_release должны быть реализованы для всех IUnknown
s. Конструктор intrusive_ptr
уже имеет удобную функцию, чтобы пропустить добавление другой ссылки, поскольку многие функции COM будут делать AddRef()
для вас.
Теперь есть одна проблема с этим подходом: intrusive_ptr не раскрывает свой основной указатель, как некоторые из других указателей COM. Это проблема, поскольку обычный способ создания COM-объектов заключается в передаче указателя на указатель на некоторую функцию создания в другом объекте. Поскольку вы не можете передать intrusive_ptr в эти функции, вы получаете неуклюжие временные указатели, которые используются для инициализации intrusive_ptr. Это не очень элегантно, не говоря уже об исключительной безопасности (если вам это нужно вообще с COM-кодом, который, естественно, не бросает исключения. Я переводит COM-ошибки в исключения, хотя.)
Итак, я здесь использую другую функцию инструмента, которая превращает функцию, которая принимает любую ком-функцию, и возвращает вызываемый, где любой параметр, являющийся указателем-на-указатель-to-T, может быть либо ссылкой, либо ссылкой на intrusive_ptr. Все остальное похоже на "функцию ввода". Затем эти функции выполняют все преобразования между T ** и intrusive_ptr & для меня. Например, HRESULT CreateBuffer(IBuffer** bufferOut, int size)
становится вызываемым с сигнатурой HRESULT CreateBuffer(instrusive_ptr<IBuffer>& bufferOut, int size)
. Они немного утомительны, чтобы писать для "всех" артефактов, если у вас нет генератора кода, большого терпения или, я полагаю, вариативных шаблонов. Но как только вы их получите, это действительно делает работу с COM очень приятной.
Ответ 3
Я использовал первые два, CComPtr и _com_ptr_t.
Похоже, вы уже прочитали о различиях с ошибками и обработкой исключений, поэтому выберите тот, который вам больше всего понравился, или который наиболее точно соответствует остальной части обработки ошибок в вашем коде.
Ответ 4
В качестве kenny
вы можете использовать CComPtr
для управления указателями на COM-интерфейсы. Этот класс хорошо документирован (см. msdn) и использует автоматический подсчет ссылок, что, я полагаю, вы хотите.
Вопрос OTOH, Rob
важен: действительно ли вы используете COM-интерфейсы? Для простых указателей вы можете использовать интеллектуальные указатели из библиотек STL
или boost
, которые в любом случае лучше (в общем), чем CComPtr
.