Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.03.16;
Скачать: CL | DM;

Вниз

Объясните, пожалуйста, смысл фразы.   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.011 c
2-1203247667
Knob
2008-02-17 14:27
2008.03.16
FTP соединение


2-1203420371
mishkas
2008-02-19 14:26
2008.03.16
Как из DataTimePicker получить переменные Year/Month/day


15-1202207039
Ins
2008-02-05 13:23
2008.03.16
Объясните, пожалуйста, смысл фразы.


15-1202049248
AntonUSAnoV
2008-02-03 17:34
2008.03.16
Delphi виснет !


2-1203077395
Quart
2008-02-15 15:09
2008.03.16
Exception EPrinter