Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, samius, Вы писали:
G>>>>>Тогда приведи корректный с точки зрения COM способ получения разных указателей на IUnknown для одного объекта.
S>>>>Обращение к QI может вернуть другой указатель, чем указатель, по которому к нему обратились. Так как любой интерфейс COM (даже еще не объявленный) расширяет IUnknown, то любой указатель, вернувшийся из QI является указателем на IUnknown.
G>>>Что значит "является указателем IUnknown" ? Тут ты говоришь в терминах ООП в С++. С точки зрения COM единственный способ получения IUnknown — выполнить QUeryInterface. Я и говорю. что ты рассматриваешь какую-то смесь COM и C++, которая COM не является.
S>>S>>All interfaces in COM are polymorphic with IUnknown, that is, if you look at the first three functions in any interface you see QueryInterface, AddRef, and Release. In other words, IUnknown is base interface from which
S>>all other interfaces inherit.
S>>Посему указатель на любой интерфейс любого COM объекта есть указатель на IUnknown.
G>И? Приведение типа в смысле C++ не является корректной операцией в COM. Для этого надо делать QueryInterface.
Предлагаю отказаться от бесполезной полемики о легальности кода
IUnknown *pUnk2;
pUnk->QueryInterface(IID_IDispatch, &pUnk2);
Бесполезная она потому как не приведет ни к чему.
Предлагаю рассмотреть следующий пример:
IXXX *pXXX;
IYYY *pYYY;
pUnk->QueryInterface(IID_IXXX, &pXXX);
pUnk->QueryInterface(IID_IYYY, &pYYY);
// HRESULT-ы корректные, в pXXX и pYYY не NULL-ы, pXXX != pYYY
Для того что бы узнать, указывают ли pXXX и pYYY на интерфейсы одного COM объекта, по спеке нужно у pXXX и pYYY вызвать QI(IID_IUnknown, &tmp) и сравнить вернувшиеся указатели.
Вопрос, существует ли способ реализовать QI БЕЗ ИСПОЛЬЗОВАНИЯ СОСТОЯНИЯ корректным образом (в соответствии со спекой), что бы он в случе различных pXXX и pYYY вернул одинаковый результат?
S>>>>Напиши все-таки код QI, разрешающий навигацию между интерфейсами и не использующий состояние. Или все-таки признай, что COM identity test использует состояние.
G>>>Ты же сам писал что если наблюдаемое поведение не зависит от состояния, то значит совсем не зависит.
S>>Ты же был там со мной категорически несогласен. А тут ссылаешься на меня?
G>Нет, я лишь сказал что вычисления можно заменить константой если они вычисляют одно и то же значение.
Ой, что я проглядел-то (смотрю на выделенное)!
Давай разберемся. QI — это такая функция, которая формально множество идентификаторов отображает на множество указателей
QI: GUID -> void*
Так вот, QI(IID_IUnknown) должна возвращать указатель на IUnknown грань. В нетривиальных случаях, когда объект имеет multiple interface, результат QI(IID_IUnknown) должен где-то хранитсья. Подозреваю что в состоянии, а никак не в константе. И QI должна будет взять указатель из состояния и вернуть его. И ты называешь это независимостью от состояния? Я ничего не попутал?
G>>>В случае COM это выполняется.
S>>Нет. Нигде не написано что QI не может изменять состояние объекта. Более того, оно именно это и делает, согласно многим сценариям COM.
G>Покажи пример чтоли.
Вот пример такого сценария из спеки (3.3.1.1)
In contrast, queries for interfaces other than IUnknown are not required to return the same
actual pointer value each time a QueryInterface returning one of them is called. This, among
other things, enables sophisticated object implementors to free individual interfaces on
their objects when they are not being used, recreating them on demand (reference
counting is a per-interface notion, as is explained further below).
S>>QI не является детерминированной в общем случае.
G>Для IUnknown — является. Этого достаточно.
Этого недостаточно что бы считать QI независящей от состояния даже в случае IUnknown.
G>>>Если нужна реализация, то пусть возвращается всегда первый face.
S>>Я не понял, что такое первый face, откуда он берется, и почему он должен быть именно IUnknown гранью.
G>Первый по порядку (любому).
Первый face по любому порядку не обязан быть IUnknown фэйсом, о чем ты?