В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения.
Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код:
Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
Здравствуйте, Melamed, Вы писали:
M>Конструкция вроде работает правильно
Это очень странно, поскольку static_cast не должен допускать столь вольных преобразований. Он может преобразовать void * в указатель на тип и наоборот, но не обычный числовой тип к указателю на тип. Что за компилятор такое допускает?
M>нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
Это зависит только от того, кто владеет указателем на интерфейс. Обычно в COM подразумевается, что любое копирование указателя должно сопровождаться вызовом AddRef, а уничтожение копии — вызовом Release. На практике от этого иногда отступают.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, Melamed, Вы писали:
M>>Конструкция вроде работает правильно
ЕМ>Это очень странно, поскольку static_cast не должен допускать столь вольных преобразований. Он может преобразовать void * в указатель на тип и наоборот, но не обычный числовой тип к указателю на тип. Что за компилятор такое допускает?
Среда разработки MSVS Enterprise 2015 Версия 14.0.25431.01 Update 3
Здравствуйте, Melamed, Вы писали:
M>Среда разработки MSVS Enterprise 2015 Версия 14.0.25431.01 Update 3
У меня есть 2015 (14.00.24215.1) — ее компилятор по умолчанию выдает на такое ошибку 2440. И все остальные версии компиляторов тоже. Преобразования разнородных типов положено выполнять с помощью reinterpret_cast (предпочтительно), function-style cast или C-style cast.
Такое впечатление, что у Вас в конфигурации проекта есть какие-то параметры, снижающие требовательность компилятора.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, Melamed, Вы писали:
M>>Среда разработки MSVS Enterprise 2015 Версия 14.0.25431.01 Update 3
ЕМ>У меня есть 2015 (14.00.24215.1) — ее компилятор по умолчанию выдает на такое ошибку 2440. И все остальные версии компиляторов тоже. Преобразования разнородных типов положено выполнять с помощью reinterpret_cast (предпочтительно), function-style cast или C-style cast.
Обратите внимание на выделение жирным шрифтом. Фактически это позволяет преобразовывать указатель на любой тип данных к конкретному указателю, так что противоречий я тут не вижу.
Здравствуйте, Melamed, Вы писали:
M>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения. M>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код: M>
Использовать static_cast тут некорректно, надо использовать reinterpret_cast или сишный (IWICBitmapDecoder*)lParam. Удивлен, что это собралось. Предупреждений не выдавало?
M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
Если работает, то да, Release можно вызвать, IWICBitmapDecoder же наследник IUnknown.
Здравствуйте, Melamed, Вы писали:
M>Обратите внимание на выделение жирным шрифтом.
Пардон, не заметил. И не только я. Но так очень не рекомендуется делать. Я в самом начале перехода с C на C++ заменил все C-style casts на function-style, и долгое время обходился только ими, пока не нарвался на совершенно неадекватное сочетание типов (по-моему, в макросе, иначе бы заметил сразу), для которого такое преобразование прокатывало по-тихому. reinterpret_cast такого ужаса не допускает.
Здравствуйте, пффф, Вы писали:
П>Здравствуйте, Melamed, Вы писали:
M>>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения. M>>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код: M>>
П>Использовать static_cast тут некорректно, надо использовать reinterpret_cast или сишный (IWICBitmapDecoder*)lParam. Удивлен, что это собралось. Предупреждений не выдавало?
Ни каких предупреждений ни в 32-битной версии ни в 64-битной версии не было
Здравствуйте, Melamed, Вы писали:
M>Здравствуйте
M>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения. M>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код: M>
M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс. Это подтверждает, при данном преобразовании не происходит вызова метода QueryInterface или AddRef не происходит. Следовательно, вызов метода Releace данного интерфейса в приведенном в вопросе коде не требуется и даже запрещен. В противном случае разрушится COM объект в коде, откуда посылается данное оконное сообщение, что может быть фатально для вашей программы
M>Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс.
Здравствуйте, Melamed, Вы писали:
M>При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс.
А должно?
M>Это подтверждает, при данном преобразовании не происходит вызова метода QueryInterface или AddRef не происходит.
А должно?
M>Следовательно, вызов метода Releace данного интерфейса в приведенном в вопросе коде не требуется и даже запрещен.
С чего бы?
В противном случае разрушится COM объект в коде, откуда посылается данное оконное сообщение
Я ж объяснил: все определяется контрактом. По умолчанию в COM принято, что любое копирование указателя на интерфейс сопровождается вызовом AddRef. Обычно это делает передающая/вызывающая сторона, но возможны нюансы. В Вашем случае AddRef может быть вызван до отправки оконного сообщения, тогда Release нужно вызывать Вам. Или передающая сторона может не вызывать AddRef в расчете на то, что Вы, получив указатель, не станете его никуда копировать, прекратив пользование им при возврате управления из обработчика сообщения.
Все это должно быть описано в документации — или в общем виде (правило умолчания), или в частном (в описании конкретной функции/сообщения).
Здравствуйте, σ, Вы писали:
M>>Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс.
σ>Весьма неожиданный и нетривиальный результат.
Вы интригуете меня, коллега...
Я бы сказал акцентированнее!
Этот результат прям вот просто "разрыв шаблона"
А в свете последних постов событий можно даже сказать иначЕ
Здравствуйте, Melamed, Вы писали:
M>Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс. Это подтверждает, при данном преобразовании не происходит вызова метода QueryInterface или AddRef не происходит. Следовательно, вызов метода Releace данного интерфейса в приведенном в вопросе коде не требуется и даже запрещен. В противном случае разрушится COM объект в коде, откуда посылается данное оконное сообщение, что может быть фатально для вашей программы
Лолшто? СхуПочему static_cast должен менять счетчик ссылок?
Здравствуйте, пффф, Вы писали:
П>Лолшто? СхуПочему static_cast должен менять счетчик ссылок?
"Лолшто" — это не аргумент! Ни тебе постановки задачи, ни тебе проектной документации, ни тебе "проведенных исследований" (пруф)
А Вы тут понимашь не аргументировано как-то. Сплошные "лолшто" да "схуа"... Как не внушает доверия...
Все в сад в исследования!!!
PS: народ, давайте просыпайтесь ужо! 11-ый час утра... Спросоня то реакция понятная, а вот спустя пару чашек кофе уже начинается правильный тренд, а именно истерические смефуёчки
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, Melamed, Вы писали:
M>>Конструкция вроде работает правильно
ЕМ>Это очень странно, поскольку static_cast не должен допускать столь вольных преобразований. Он может преобразовать void * в указатель на тип и наоборот, но не обычный числовой тип к указателю на тип. Что за компилятор такое допускает?
Все нормально, там два каста,внутри термоядерный c-style cast
M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
Вызывающий код должен сделать addref поскольку отдал ссылку во внешний код, а дождаться пока она гарантированно обработаеться не может.
Обработчик должен вызвать Release когда экземпляр больше не нужен.
Любое другое поведение — подарочные грабли с бантиком.
Здравствуйте, Melamed, Вы писали:
M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
Тут зависит от того, что именно передаётся и как.
Если у нас есть объект, который живёт всё время пока живёт окно, то можно и ничего не делать:
int main()
{
CComQIPtr<IWICBitmapDecoder> x;
x.CreateInstance(CLSID_WICBitmapDecoder);
// псевдоокд
wndProc.lParam = &x;
HWND window = CreateWindow(... wndProc);
// псевдокод
Wait for window to close
// Далее не будет вызовов WndProc.
} // Здесь вызовется деструктор и освободится ссылка.
WndProc(HWND,int,LPARAM lParam,WPARAM wParam)
{
// Ок. Объект жив, счётчик ссылок будет как минимум 1.
IWICBitmapDecoder *pDecoder = reinterpret_cast<IWICBitmapDecoder*>(lParam);
}
Здравствуйте, Melamed, Вы писали:
M>Здравствуйте
M>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения. M>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код: M>
M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
А кто этот интерфейс в параметр сообщения пакует? Если ты сам сообщение отправляешь, то очевидно ты сам и решаешь.
Если ты не увеличивал счетчик ссылок, но и уменьшать (вызывать Release) не надо.
Приведения static_cast<> или (void*) на счетчик ссылок никак не влияют.
Если бы у тебя были умные указатели, тогда другое дело, а если как здесь — "сырые", ничего неявного происходить не будет.
Это же чисто синтаксис для того чтобы можно было один и тот же набор байтов интерпретировать по-разному.