Форум: "Прочее";
Текущий архив: 2008.03.16;
Скачать: [xml.tar.bz2];
ВнизОбъясните, пожалуйста, смысл фразы. Найти похожие ветки
← →
Ins © (2008-02-05 13:23) [0]Здравствуйте. У меня вопрос следующий... Объясните пожалуйста смысл фразы "для совместимости с COM, в Delphi тип классовая ссылка представляет собой указатель на VMT".
← →
clickmaker © (2008-02-05 13:33) [1]COM - это интерфейсы.
Интерфейс - это VMT, таблица методов
а где эта фраза живет?
← →
Ins © (2008-02-05 13:39) [2]
> а где эта фраза живет?
Прошу прощения. Фразу по памяти воспроизвел неверно. Правильно так:
Итак, этот метод возвращает адрес, на который указывают самые первые четыре байта в теле объекта. Нам это вряд ли помогло бы, если бы не знание о совместимости Delphi с COM. Как известно, структура COM-объектов строго стандартизована. В начале объекта должен быть расположен указатель на VMT. Дополнительным подтверждением этому служат константы с именами, начинающимися на vmt*, определенные в модуле System:
Источник - http://rsdn.ru/article/Delphi/delphiabs.xml
Я так понимаю, это справедливо для более старых версий Delphi, так как сейчас по смещениям 0, 4 и 8 в VMT может храниться в общем случае все, что угодно, а не указатели на методы IUnknown
← →
хам (2008-02-05 13:40) [3]> [2] Ins © (05.02.08 13:39)
> так как сейчас по смещениям 0, 4 и 8 в VMT может храниться
> в общем случае все, что угодно
А что изменилось?
← →
Ins © (2008-02-05 13:44) [4]
> А что изменилось?
В юните System.pas есть такое описание:vmtQueryInterface = 0 deprecated;
vmtAddRef = 4 deprecated;
vmtRelease = 8 deprecated;
Я так понимаю, раньше первые 4 байта объекта указывали на VMT интерфейса IUnknown, а сейчас вроде бы нет.
← →
хам (2008-02-05 13:48) [5]> [4] Ins © (05.02.08 13:44)
> а сейчас вроде бы нет.
Может и сейчас да, а deprecated, ну потому что просто deprecated, на дворе 21 век, ООП, управляемый код, а здесь по кишкам лазить…
← →
Ins © (2008-02-05 13:54) [6]
> Может и сейчас да
Эксперимент тоже показывает, что для Delphi 7 там может быть все, что угодно. Т.е. правильно ли я понимаю, что раньше для совместимости с COM в VMT всех классов первые три ячейки были зарезервированы, а получение интерфейса IUnknown сводилось к прочтению первых 4 байт от начала экземпляра, но с тех пор объектная модель несколько изменилась?
← →
Ins © (2008-02-05 14:01) [7]
> Прошу прощения. Фразу по памяти воспроизвел неверно.
Хотя верно. Там в конце делается такой вывод:
Итак, 4 байта, полученных при вызове TObject.ClassType, указывают в начало таблицы виртуальных методов, декларированных в потомках TObject. Этот вывод можно считать «безопасным» до тех пор, пока Delphi поддерживает совместимость с COM.
← →
clickmaker © (2008-02-05 14:01) [8]поменяли способ нахождения ссылки на метод
раньше по vmtQueryInterface и пр.
а теперь по VMTOFFSET IInterface.QueryInterface
см. _IntfCast в system.pas
← →
Григорьев Антон © (2008-02-05 14:13) [9]
> Ins © (05.02.08 13:39) [2]
Фраза "структура COM-объектов строго стандартизована" неправильная. До структуры COM-объекта вообще дела никому нет. Единственное требование к нему - чтобы он умел возвращать указатели на интерфейсы (на бинарном уровне это указатель на указатель на VMT интерфейса). А уж как он сам внутри устроен - не важно. В C++, например, интерфейс - это просто класс, у которого нет полей, а все методы абстрактны и имеют видимость public. Реализация интерфейсов в COM-объекте часто делается множественным наследованием, и этих интерфейсов будет несколько. Соответственно, и несколько VMT будет, и по какому смещению в данных класса они будут располагаться, заранее неизвестно, особенно если наследуются не только интерфейсы, но и классы. И ничего, всё работает.
Вообще, в C++ объявление виртуальных методов в классе означает, что появляется неявное поле void* vPtr, являющееся указателем на VMT. Представьте, что класс наследуется от другого класса, и предок не содержит виртуальных методов, но имеет другие, явно объявленные поля. Тогда vPtr наследника помещается после этих полей, а вовсе не в начало класса, иначе будет нарушена совместимость с предком. Так что в общем случае даже без множественного наследования нельзя предсказать, по какому смещению будет находится указатель на VMT. А в случае множественного наследования в классе появляются унаследованные неявные vPtr1, vPtr2 и т.п., каждый со своим смещением. И такая сложная структура ещё никому не мешала делать COM-объекты на C++.
Как устроены классы и где там хранятся указатели на VMT интерфейсов, я не знаю. Но вы можете попробовать связаться с Инной Аринович (модератор Круглого стола), она когда-то давно детально разбиралась с этим, может, вспомнит.
← →
Ins © (2008-02-05 14:14) [10]
> clickmaker © (05.02.08 14:01) [8]
Для того, чтобы вызвать метод QueryInterface мало знать только VMTOFFSET IInterface.QueryInterface. Нужен еще и адрес самого интерфейса. Вопрос в том, был ли он раньше фиксированным и совпадал ли с адресом VMT класса?
Может есть у кого-нибудь system.pas, где vmtQueryInterface еще не deprecated?
← →
Ins © (2008-02-05 14:29) [11]
> Как устроены классы и где там хранятся указатели на VMT
> интерфейсов, я не знаю.
Ну я с этим вроде пробовал разбираться, эксперименты на D7 и выше показали, что VMT для класса хранится по смещению 0 в экземпляре всегда. Но каждый интерфейс, который класс реализует, также добавляет в экземпляр неявные поля - ссылки на свои VMT. И они располагаются по некоторым смещениям от начала объекта в памяти. Эти смещения можно узнать из структуры TInterfaceEntry (поле IOffset), да не суть.
Т.е. например, для объекта TA(TSomeClass, IInterface, IA) внутреннее устройство может быть таким:
0: Указатель на VMT класса TA
4. Некое поле объекта, объявленное еще в классе TSomeClass
8. Указатель на VMT интерфейса IInterface
12. Указатель на VMT интерфейса IA
Т.е. каждый новый интерфейс (IInterface в том числе) добавляет к объекту 4 байта - указатель на VMT этого интерфейса. Тут ситуация та же, что и с множественным наследованием в C++ - каждый новый предок (интерфейсного типа) добавляет после полей предка указатель на свой VMT. Но так реализовано в D7 и выше. Объявления vmtQueryInterface и прочие говорят о том, что раньше указатель на VMT класса автоматически был указателем на VMT интерфейса IUnknown. Похоже с тех пор это в объектной модели изменилось, но хотелось бы знать точно.
← →
Ins © (2008-02-05 14:33) [12]
> Фраза "структура COM-объектов строго стандартизована" неправильная.
> До структуры COM-объекта вообще дела никому нет. Единственное
> требование к нему - чтобы он умел возвращать указатели на
> интерфейсы
Я тоже к этому склонялся, а раз так - то это многое объясняет.
← →
kami (2008-02-05 14:50) [13]Ins © (05.02.08 14:14) [10]
Может есть у кого-нибудь system.pas, где vmtQueryInterface еще не deprecated
Есть от D5.
← →
Ins © (2008-02-05 14:51) [14]
> Есть от D5.
Там vmtQueryInterface как deprecated объявлено?
← →
Kolan © (2008-02-05 15:16) [15]>
> Там vmtQueryInterface как deprecated объявлено?
Delphi 5:vmtQueryInterface = 0;
vmtAddRef = 4;
vmtRelease = 8;
vmtCreateObject = 12;
DDS 2006:vmtSafeCallException = —32 deprecated; // don’t use these constants.
vmtAfterConstruction = —28 deprecated; // use VMTOFFSET in asm code instead
vmtBeforeDestruction = —24 deprecated;
vmtDispatch = —20 deprecated;
vmtDefaultHandler = —16 deprecated;
vmtNewInstance = —12 deprecated;
vmtFreeInstance = —8 deprecated;
vmtDestroy = —4 deprecated;
vmtQueryInterface = 0 deprecated;
vmtAddRef = 4 deprecated;
vmtRelease = 8 deprecated;
vmtCreateObject = 12 deprecated;
← →
Ins © (2008-02-05 15:19) [16]О! Тогда если можно - скиньте сюда, пожалуйста:
randr_insСОБАКАserverТОЧКАby
← →
Kolan © (2008-02-05 15:23) [17]Ушло
← →
Asker (2008-02-05 15:29) [18]какой кошмар
Автор, Вам больше нечем заняться?
внутренняя реализация классовой ссылке сделана с учётом совместимости с технологией COM
ВСЁ - больше ничего знать не надо
← →
Ins © (2008-02-05 15:30) [19]Пришло, спасибо. Дома его препарирую :) В принципе, это + ответ Антона про "неверное утверждение" - вполне исчерпывающее решение. Всем спасибо!
← →
Ins © (2008-02-05 15:31) [20]
> ВСЁ - больше ничего знать не надо
Да вообще много знать вредно, говорят на сон плохо влияет ;-)
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2008.03.16;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.006 c