static_cast и COM интерфейсы
От: Melamed Россия  
Дата: 01.02.23 11:05
Оценка:
Здравствуйте

В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения.
Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код:
IWICBitmapDecoder *pDecoder = static_cast<IWICBitmapDecoder*>((void*)lParam);
if (pDecoder != nullptr)
{
    lResult = ecSetWICDecoder(pDecoder);
}


Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?
Re: static_cast и COM интерфейсы
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 01.02.23 11:17
Оценка: -1
Здравствуйте, Melamed, Вы писали:

M>Конструкция вроде работает правильно


Это очень странно, поскольку static_cast не должен допускать столь вольных преобразований. Он может преобразовать void * в указатель на тип и наоборот, но не обычный числовой тип к указателю на тип. Что за компилятор такое допускает?

M>нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?


Это зависит только от того, кто владеет указателем на интерфейс. Обычно в COM подразумевается, что любое копирование указателя должно сопровождаться вызовом AddRef, а уничтожение копии — вызовом Release. На практике от этого иногда отступают.
Re[2]: static_cast и COM интерфейсы
От: Melamed Россия  
Дата: 01.02.23 11:30
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Melamed, Вы писали:


M>>Конструкция вроде работает правильно


ЕМ>Это очень странно, поскольку static_cast не должен допускать столь вольных преобразований. Он может преобразовать void * в указатель на тип и наоборот, но не обычный числовой тип к указателю на тип. Что за компилятор такое допускает?


Среда разработки MSVS Enterprise 2015 Версия 14.0.25431.01 Update 3
Re[3]: static_cast и COM интерфейсы
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 01.02.23 11:40
Оценка:
Здравствуйте, 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.

Такое впечатление, что у Вас в конфигурации проекта есть какие-то параметры, снижающие требовательность компилятора.
Re[4]: static_cast и COM интерфейсы
От: Melamed Россия  
Дата: 01.02.23 12:08
Оценка: 1 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, 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.


IWICBitmapDecoder *pDecoder = static_cast<IWICBitmapDecoder*>((void*) lParam);


Обратите внимание на выделение жирным шрифтом. Фактически это позволяет преобразовывать указатель на любой тип данных к конкретному указателю, так что противоречий я тут не вижу.
Re: static_cast и COM интерфейсы
От: пффф  
Дата: 01.02.23 12:12
Оценка: -1
Здравствуйте, Melamed, Вы писали:

M>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения.

M>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код:
M>
M>IWICBitmapDecoder *pDecoder = static_cast<IWICBitmapDecoder*>((void*)lParam);
M>if (pDecoder != nullptr)
M>{
M>    lResult = ecSetWICDecoder(pDecoder);
M>}
M>


Использовать static_cast тут некорректно, надо использовать reinterpret_cast или сишный (IWICBitmapDecoder*)lParam. Удивлен, что это собралось. Предупреждений не выдавало?


M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?


Если работает, то да, Release можно вызвать, IWICBitmapDecoder же наследник IUnknown.
Re[5]: static_cast и COM интерфейсы
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 01.02.23 12:17
Оценка: 1 (1)
Здравствуйте, Melamed, Вы писали:

M>Обратите внимание на выделение жирным шрифтом.


Пардон, не заметил. И не только я. Но так очень не рекомендуется делать. Я в самом начале перехода с C на C++ заменил все C-style casts на function-style, и долгое время обходился только ими, пока не нарвался на совершенно неадекватное сочетание типов (по-моему, в макросе, иначе бы заметил сразу), для которого такое преобразование прокатывало по-тихому. reinterpret_cast такого ужаса не допускает.
Re[2]: static_cast и COM интерфейсы
От: Melamed Россия  
Дата: 01.02.23 12:31
Оценка:
Здравствуйте, пффф, Вы писали:

П>Здравствуйте, Melamed, Вы писали:


M>>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения.

M>>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код:
M>>
M>>IWICBitmapDecoder *pDecoder = static_cast<IWICBitmapDecoder*>((void*)lParam);
M>>if (pDecoder != nullptr)
M>>{
M>>    lResult = ecSetWICDecoder(pDecoder);
M>>}
M>>


П>Использовать static_cast тут некорректно, надо использовать reinterpret_cast или сишный (IWICBitmapDecoder*)lParam. Удивлен, что это собралось. Предупреждений не выдавало?


Ни каких предупреждений ни в 32-битной версии ни в 64-битной версии не было
Re[2]: static_cast и COM интерфейсы
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 01.02.23 12:41
Оценка: 2 (2) +2 :))
Здравствуйте, пффф, Вы писали:

П>Удивлен, что это собралось. Предупреждений не выдавало?


Дык, сочетание static_cast с C-style cast — это сильно.
Re: static_cast и COM интерфейсы
От: Melamed Россия  
Дата: 01.02.23 21:38
Оценка: :))) :)))
Здравствуйте, Melamed, Вы писали:

M>Здравствуйте


M>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения.

M>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код:
M>
M>IWICBitmapDecoder *pDecoder = static_cast<IWICBitmapDecoder*>((void*)lParam);
M>if (pDecoder != nullptr)
M>{
M>    lResult = ecSetWICDecoder(pDecoder);
M>}
M>


M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?


Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс. Это подтверждает, при данном преобразовании не происходит вызова метода QueryInterface или AddRef не происходит. Следовательно, вызов метода Releace данного интерфейса в приведенном в вопросе коде не требуется и даже запрещен. В противном случае разрушится COM объект в коде, откуда посылается данное оконное сообщение, что может быть фатально для вашей программы

Программист = младший научный сотрудник
Re[2]: static_cast и COM интерфейсы
От: σ  
Дата: 01.02.23 21:46
Оценка: 6 (1) +3 :))) :)
M>Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс.

Весьма неожиданный и нетривиальный результат.
Re[2]: static_cast и COM интерфейсы
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 01.02.23 22:11
Оценка: :)
Здравствуйте, Melamed, Вы писали:

M>При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс.


А должно?

M>Это подтверждает, при данном преобразовании не происходит вызова метода QueryInterface или AddRef не происходит.


А должно?

M>Следовательно, вызов метода Releace данного интерфейса в приведенном в вопросе коде не требуется и даже запрещен.


С чего бы?

В противном случае разрушится COM объект в коде, откуда посылается данное оконное сообщение

Я ж объяснил: все определяется контрактом. По умолчанию в COM принято, что любое копирование указателя на интерфейс сопровождается вызовом AddRef. Обычно это делает передающая/вызывающая сторона, но возможны нюансы. В Вашем случае AddRef может быть вызван до отправки оконного сообщения, тогда Release нужно вызывать Вам. Или передающая сторона может не вызывать AddRef в расчете на то, что Вы, получив указатель, не станете его никуда копировать, прекратив пользование им при возврате управления из обработчика сообщения.

Все это должно быть описано в документации — или в общем виде (правило умолчания), или в частном (в описании конкретной функции/сообщения).
Re[3]: static_cast и COM интерфейсы
От: Carc Россия http://www.amlpages.com/home.php
Дата: 02.02.23 07:08
Оценка:
Здравствуйте, σ, Вы писали:

M>>Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс.


σ>Весьма неожиданный и нетривиальный результат.

Вы интригуете меня, коллега...
Я бы сказал акцентированнее!
Этот результат прям вот просто "разрыв шаблона"
А в свете последних постов событий можно даже сказать иначЕ

Разрыв так называемого шаблона.
Но это другое ©

Aml Pages Home
Re[2]: static_cast и COM интерфейсы
От: пффф  
Дата: 02.02.23 07:16
Оценка: +1
Здравствуйте, Melamed, Вы писали:

M>Мое исследование показало: При преобразовании типа void* в IWICBitmapDecoder* с помощью оператора static_cast не меняется количество ссылок на данный интерфейс. Это подтверждает, при данном преобразовании не происходит вызова метода QueryInterface или AddRef не происходит. Следовательно, вызов метода Releace данного интерфейса в приведенном в вопросе коде не требуется и даже запрещен. В противном случае разрушится COM объект в коде, откуда посылается данное оконное сообщение, что может быть фатально для вашей программы


Лолшто? СхуПочему static_cast должен менять счетчик ссылок?
Re[3]: static_cast и COM интерфейсы
От: Carc Россия http://www.amlpages.com/home.php
Дата: 02.02.23 07:37
Оценка:
Здравствуйте, пффф, Вы писали:

П>Лолшто? СхуПочему static_cast должен менять счетчик ссылок?

"Лолшто" — это не аргумент! Ни тебе постановки задачи, ни тебе проектной документации, ни тебе "проведенных исследований" (пруф)
Автор: Melamed
Дата: 02.02.23
, про тендер даже и говорить не приходится...

А Вы тут понимашь не аргументировано как-то. Сплошные "лолшто" да "схуа"... Как не внушает доверия...
Все в сад в исследования!!!


PS: народ, давайте просыпайтесь ужо! 11-ый час утра... Спросоня то реакция понятная, а вот спустя пару чашек кофе уже начинается правильный тренд, а именно истерические смефуёчки
Aml Pages Home
Re[2]: static_cast и COM интерфейсы
От: Teolog  
Дата: 03.02.23 20:19
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Melamed, Вы писали:


M>>Конструкция вроде работает правильно


ЕМ>Это очень странно, поскольку static_cast не должен допускать столь вольных преобразований. Он может преобразовать void * в указатель на тип и наоборот, но не обычный числовой тип к указателю на тип. Что за компилятор такое допускает?


Все нормально, там два каста,внутри термоядерный c-style cast
Re: static_cast и COM интерфейсы
От: Teolog  
Дата: 03.02.23 20:29
Оценка: 10 (1)
M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?

Вызывающий код должен сделать addref поскольку отдал ссылку во внешний код, а дождаться пока она гарантированно обработаеться не может.
Обработчик должен вызвать Release когда экземпляр больше не нужен.

Любое другое поведение — подарочные грабли с бантиком.
Re[3]: static_cast и COM интерфейсы
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 03.02.23 22:16
Оценка:
Здравствуйте, Teolog, Вы писали:

T>Все нормально


Где там "нормально"?

T>внутри термоядерный c-style cast


Вот именно поэтому.
Re: static_cast и COM интерфейсы
От: _NN_ www.nemerleweb.com
Дата: 04.02.23 12:42
Оценка:
Здравствуйте, 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);
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: static_cast и COM интерфейсы
От: bnk СССР http://unmanagedvisio.com/
Дата: 20.07.23 10:25
Оценка:
Здравствуйте, Melamed, Вы писали:

M>Здравствуйте


M>В моей программе COM интерфейс IWICBitmapDecoder передается моему управляющему элементу через lParam сообщения.

M>Чтобы в оконной функции использовать параметр lParam как указанный COM интерфейс, использую следующую код:
M>
M>IWICBitmapDecoder *pDecoder = static_cast<IWICBitmapDecoder*>((void*)lParam);
M>if (pDecoder != nullptr)
M>{
M>    lResult = ecSetWICDecoder(pDecoder);
M>}
M>


M>Конструкция вроде работает правильно, но встает вопрос: нужно ли в данном коде для освобождения ресурсов использовать метод Release интерфейса IUnknown или нет?


А кто этот интерфейс в параметр сообщения пакует? Если ты сам сообщение отправляешь, то очевидно ты сам и решаешь.
Если ты не увеличивал счетчик ссылок, но и уменьшать (вызывать Release) не надо.

Приведения static_cast<> или (void*) на счетчик ссылок никак не влияют.
Если бы у тебя были умные указатели, тогда другое дело, а если как здесь — "сырые", ничего неявного происходить не будет.
Это же чисто синтаксис для того чтобы можно было один и тот же набор байтов интерпретировать по-разному.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.