Как интерфейсы устроены "под капотом"?

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Как интерфейсы устроены "под капотом"?

Сообщение Cheb » 05.03.2019 11:41:19

Анатомия TObject - распространённое знание, в инете полно подробных разборов.
Но по анатомии интерфейсов - ничего не находится, кроме ссылок на стандартные способы работы с ними.
Но хороший паскалист должен знать, как оно устроено там, внутри.

Пытался сделать сериализацию, как уже сделал для объектов. Ниасилил (без уродливых костылей, по крайней мере).

Размер TInterfacedObject - 12 байт, против 4 у TObject, НО! Я уже выяснил экспериментальным путём, что ФП расточительно расходует память в процессе наследования: размеры классов выравниваются на 8 байт, что часто приводит к неиспользуемым дыркам между полями наследника и предка. Таким образом, расклад TInterfacedObject скорее всего: 4 байта указатель на VMT / 4 байта просрано / 4 байта интерфейс).

Базовые исследования показали: переменная типа интерфейс - это такая же ссылка, указывает куда-то внутрь экземпляра класса. В случае моих экспериментов - по смещению 8 от начала. По этому адресу - тоже ссылка, но уже на неизвестно что. В принципе, VMT и это неизвестно-что расположены достаточно близко друг к другу (например, 00426028 и 004260B4).

Попытки парсить память уже по этому указателю (там, в свою очередь, оказался массив указателей) дают следующую картину:
Код: Выделить всё
  (00402150)  04246C83  F726E908  0000FFFF  00000000
  (00402160)  04246C83  F636E908  0000FFFF  00000000
  (00402170)  04246C83  F686E908  0000FFFF  00000000
  (30427B26)An unhandled exception occurred at $00401B62:
EAccessViolation: Access violation

-- до боли похоже на VMT, тем более, что методов в том интерфейсе - как раз три.

Так вот, вопрос: у кого нибудь есть ссылки на материалы по тому, как устроена эта "интерфейсовая VMT" и с чем её едят?
Вполне возможно, что материалы по ЦПП подойдут: интерфейсы ведь, теоретически, это кросс-языковый стандарт.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 708
Зарегистрирован: 06.06.2005 15:54:34

Re: Как интерфейсы устроены "под капотом"?

Сообщение Vadim » 05.03.2019 12:02:55

Cheb писал(а):как устроена эта "интерфейсовая VMT"

Если брать интерфейсы сами по себе, то у них все ссылки на методы ведут в пустоту. Собственно так и должно быть. Т.е. никак она не устроена. Это то, чего нет. ;-) Присвоите "интерфейсной" переменной какой-нибудь созданный класс, тогда появятся ссылки, которые указывают на реализацию методов класса.
Cheb писал(а): и с чем её едят?

Её едят с классами. Сама по себе она несъедобна, как пустая коробка от торта. Внутри должен быть торт, которым заведует класс.

Cheb писал(а):есть ссылки на материалы по тому, как устроена эта "интерфейсовая VMT"

Только если вместе с Дельфями. Правда и там, кроме "точка, точка, запятая - вышла рожица кривая..." Вы ничего не найдёте.
Vadim
долгожитель
 
Сообщения: 3450
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Как интерфейсы устроены "под капотом"?

Сообщение Sergei I. Gorelkin » 05.03.2019 13:13:08

Просто массив адресов методов, ничего больше. Возможно, потому и не документировано, что совсем уж элементарно.
Если интерфейс реализуется классом непосредственно (не через делегацию), то каждый метод интерфейса - это переходник, который вычитает смещение из self и прыгает на соответствующий метод класса.

В TInterfacedObject, если что, есть еще счетчик ссылок, в 32-битном варианте как раз 12 байт получается.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1381
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Как интерфейсы устроены "под капотом"?

Сообщение Cheb » 05.03.2019 16:29:00

есть еще счетчик ссылок, в 32-битном варианте как раз 12 байт получается.

(рукалицо) совсем про него забыл.

Значит, получается, что для каждой комбинации "класс х интерфейс" заведена отдельная "интерфейсо-VMT", и при M классов знающих N интерфейсов компилятор сгенерирует в сегменте кода M * N таких заполненных таблиц.

А при присваивании объекта интерфейсной переменной, компилятор генерирует код, который лезет в vmt этого объекта за смещением на данный конкретный интерфейс (зашито в код оператора), и записывает указатель на экземпляр плюс это смещение. То есть, операция относительно дешёвая.

Главная же магия творится при создании объекта, когда метод TObject.InitInstance вызывает InitInterfacePointers() и по всем положенным смещениям раскладывает указатели на нужные интерфейсо-VMT.

И ещё, если M классов знает N интерфейсов с K методами, то компилятор сгенерит M * N * K обёрток?

Я правильно догадался?

...совсем не бесплатно получается. Хорошо что я вовремя одумался свой движок на интерфейсах делать.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 708
Зарегистрирован: 06.06.2005 15:54:34

Re: Как интерфейсы устроены "под капотом"?

Сообщение Sergei I. Gorelkin » 05.03.2019 17:11:26

Cheb писал(а):И ещё, если M классов знает N интерфейсов с K методами, то компилятор сгенерит M * N * K обёрток?

Где-то примерно так и будет...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1381
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Как интерфейсы устроены "под капотом"?

Сообщение sts » 05.03.2019 19:25:18

в движках просто нету места где имеет смысл применять виртуальные методы и интерфейсы, разве что у вас несколько рендереров, типа софтварный опенгл директ икс, и то там их тока пару методов будет, вызываемых один раз при инициализации. классы полиморфизм\интерфейсы хороши в гуе и бизнесзадачах.
sts
постоялец
 
Сообщения: 258
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: Как интерфейсы устроены "под капотом"?

Сообщение CynicRus » 05.03.2019 20:42:13

sts писал(а):в движках просто нету места где имеет смысл применять виртуальные методы и интерфейсы, разве что у вас несколько рендереров, типа софтварный опенгл директ икс, и то там их тока пару методов будет, вызываемых один раз при инициализации. классы полиморфизм\интерфейсы хороши в гуе и бизнесзадачах.


Да как бы под несколько рендеров можно обойтись и абстрактным классом, с наследниками и паттерном фабрика.

А вот где не обойтись, так это при написании библиотеки типов, ком объектов и пожалуй поддержки мультиязычных плагинов.
CynicRus
новенький
 
Сообщения: 84
Зарегистрирован: 28.06.2012 14:31:11

Re: Как интерфейсы устроены "под капотом"?

Сообщение Mirage » 06.03.2019 00:42:29

Про устройство интерфейсов в Delphi можно почитать тут:
http://pages.cs.wisc.edu/~rkennedy/interface-object
В FPC, думаю, похоже. В крайнем случае можно уточнить в майллисте fpc-devel. Там отвечаю вполне охотно.
Mirage
энтузиаст
 
Сообщения: 848
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Как интерфейсы устроены "под капотом"?

Сообщение gluhow » 06.03.2019 19:00:49

Пытался сделать сериализацию, как уже сделал для объектов. Ниасилил (без уродливых костылей, по крайней мере).

У меня есть проект с сериализацией интерфейсов, если интересно, могу скинуть. Уродливость оценить не могу, ничего лучше на тот момент в голову не пришло.
gluhow
новенький
 
Сообщения: 25
Зарегистрирован: 13.08.2015 15:30:20

Re: Как интерфейсы устроены "под капотом"?

Сообщение stanilar » 08.03.2019 18:28:02

Cheb писал(а):Хорошо что я вовремя одумался свой движок на интерфейсах делать


Ты даже представить себе не можешь, какого ада в отладке ты избежал. Интерфейсные переменные в рантайме могут указывать на разные объекты разных классов.

Не мной замечено, что интерфейсы это скорее механизм экспорта/импорта а не разработки.
stanilar
постоялец
 
Сообщения: 281
Зарегистрирован: 09.03.2010 19:09:02

Re: Как интерфейсы устроены "под капотом"?

Сообщение iskander » 08.03.2019 19:50:27

stanilar писал(а):Ты даже представить себе не можешь, какого ада в отладке ты избежал.
Интерфейсные переменные в рантайме могут указывать на разные объекты разных классов.

Wow! Прокукарекал, а там хоть не рассветай?
Последний раз редактировалось iskander 08.03.2019 20:18:29, всего редактировалось 1 раз.
iskander
постоялец
 
Сообщения: 142
Зарегистрирован: 08.01.2012 18:43:34

Re: Как интерфейсы устроены "под капотом"?

Сообщение stanilar » 08.03.2019 20:16:30

iskander писал(а):Прокукарекал, а там хоть не рассветай?


Ты ничего не перепутал? Курятник в другом месте.
stanilar
постоялец
 
Сообщения: 281
Зарегистрирован: 09.03.2010 19:09:02

Re: Как интерфейсы устроены "под капотом"?

Сообщение iskander » 08.03.2019 20:48:23

stanilar писал(а): Курятник в другом месте.

Ну и удачи тебе там.
iskander
постоялец
 
Сообщения: 142
Зарегистрирован: 08.01.2012 18:43:34

Re: Как интерфейсы устроены "под капотом"?

Сообщение Лекс Айрин » 08.03.2019 20:53:42

А может по теме? Все так интересно шло, а потом...
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5257
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Как интерфейсы устроены "под капотом"?

Сообщение stanilar » 08.03.2019 21:54:20

iskander писал(а):Ну и удачи тебе там.


Мне и тут хорошо.

Добавлено спустя 15 минут 40 секунд:
Лекс Айрин писал(а):А может по теме?


Ну по теме, когда для того, чтоб понять как работает код, надо запустить программу и выполнить действия, приведшие к проблемам - это сильно напрягает.

Добавлено спустя 5 минут 13 секунд:
Не хочу показаться бестактным, но вот мне понятно когда сериализуется объект а его интерфейс содержит метод сериализации. Но вот сериализация самого интерфейса...

Если мне и приходилось делать что-то похожее, то это был поиск интерфейса по его GUID. В паскале для интерфейсов же нельзя менять методы, их можно только объявить.
stanilar
постоялец
 
Сообщения: 281
Зарегистрирован: 09.03.2010 19:09:02

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Attid и гости: 5

Рейтинг@Mail.ru