Показаны сообщения с ярлыком RTTI. Показать все сообщения
Показаны сообщения с ярлыком RTTI. Показать все сообщения

пятница, 5 августа 2011 г.

Как добавить published свойство без нарушения совместимости DCU

Это перевод How to add a "published" property without breaking DCU compatibility. Автор: Allen Bauer.

Во-первых, если вы пурист ООП или фреймворков и имеете слабый желудок - лучше закройте эту страницу прямо сейчас.

В ожидаемом релизе Delphi 2007 for Win32 мы взяли беспрецедентный подход к расширению функциональности VCL. Если вы использовали Delphi более нескольких её версий, то вы очень хорошо знаете, что такое смена версии - это необходимость получить новые версии всех компонентов. Я не буду сейчас обсуждать причины этого, поскольку я уже неоднократно покрыл это в деталях за всё это время. В основном это сводится к тому, что нам нужна гибкость для внесения изменений в существующие классы и сам компилятор по своему усмотрению, чтобы обеспечить лучшее общее впечатление, какое только мы можем. Таким образом, для всех вас, кто собирается делать возмущённые комментарии по поводу "почему бы вам не делать это в каждом выпуске!?" - если бы мы делали это, то вы бы никогда не имели новых возможностей компилятора - пакетов, интерфейсов, классовых переменных, встроенных (inline) функций, а также генериков (пост-Delphi 2007). Просто просмотрите некоторые из моих прошлых постов для более подробной информации.

И несмотря на всё вышесказанное, мы решили следовать иному подходу при выпуске Delphi 2007. D2007 предназначено быть "non-breaking" выпуском. Что в точности это означает? В корне это означает, что вы можете просто взять большинство своих компонентов и модулей, собранных в BDS2006, и установить их в D2007. Я говорю "большинство" потому что, конечно же, будут какие-то краевые случаи, когда это не будет возможным. К примеру, если компонент работает с какими-то внутренними вещами в обход общедоступного/документированного интерфейса, а эти "вещи за сценой" изменены - такое поведение не является целью для "non-breaking" изменений. До тех пор, пока ваш (или сторонний) код придерживается общепринятого контракта - он будет работать без перекомпиляции.

Эмм... а что-ж тогда нового?? Это правда, что мы изменили много кода, и эти изменения были сделаны только в секции implementation - так что мы не меняли интерфейс и не нарушили совместимость двоичных DCU. Но в новостях объявлено о некоторых изменениях, которые проявляются либо в новых компонентах, либо в новых published свойствах! Правила по совместимости типов компилятора Delphi обманчиво просты. В принципе, для любого структурированного типа (класса, записи, объекта и т.п.) "версия" этого типа или символа выводится от всех входящих в его определение типов и символов. Так что вы не можете модифицировать существующий тип класса или объявление метода без смены "версии". Это приведёт к появлению сообщения об ошибке "xxx was compiled with a different version of yyy”.

Так как же мы сделали это?

воскресенье, 31 июля 2011 г.

Расширенная RTTI информация классов

Это перевод Extended Class RTTI. Автор: Hallvard Vassbotn.

Как я упоминал ранее, Delphi (начиная с версии 7) поддерживает генерацию расширенной RTTI информации о методах класса - через компиляцию класса в режиме $METHODINFO ON. Эта RTTI информация включает в себя информацию о сигнатуре public и published методов. Delphi использует её для реализации поддержки скриптинга в фреймворке WebSnap - см. модуль ObjAuto и его друзей для более подробных сведений.

Я сумел написать свои собственные определения и подпрограммы, которые выдёргивают и сохраняют расширенную RTTI информацию классов в формат, удобный для внешнего использования. Как обычно, моё тестовое приложение будет дампить тестовый класс, воссоздавая его псевдо-объявление.

суббота, 30 июля 2011 г.

Расширенная RTTI информация интерфейсов

Это перевод Extended Interface RTTI. Автор: Hallvard Vassbotn.

Чтобы поддерживать базовые механизмы SOAP архитектуры, Delphi добавила поддержку расширенной RTTI информации для интерфейсов начиная с версии 7. Как мы видели в предыдущей статье, все интерфейсы поддерживают базовую информацию RTTI: имя интерфейса, его GUID, имя модуля с объявлением, родительский интерфейс и число методов.

Чтобы добавить к интерфейсу расширенную RTTI информацию, его нужно собрать в режиме {$M+}/{$TYPINFO ON} или {$METHODINFO ON}. Альтернативно, вы можете просто унаследовать свой интерфейс от IInvokable (определённого в модуле System с $M+). Это расширит генерируемую RTTI для интерфейса информацией по сигнатуре каждого метода.

пятница, 29 июля 2011 г.

Простая RTTI информация интерфейсов

Это перевод Simple Interface RTTI. Автор: Hallvard Vassbotn.

Delphi поддерживает получение RTTI информации для всех интерфейсов, но она не включает (не генерирует) информацию о методах для "нормальных" интерфейсов:
type
  {$M-}
  IMyMMInterface = interface
    procedure Foo;
  end;

четверг, 28 июля 2011 г.

Раскапывая детали SOAP и WebSnap

Это перевод Digging into SOAP and WebSnap. Автор: Hallvard Vassbotn.

В предыдущих статьях этого блога мы досконально разобрали внутреннюю кухню работы published методов, и предположили, что RTTI для них не включает в себя сведения о сигнатуре вызова. Затем мы разработали грязный (и довольно бесполезный) хак, который откапывал параметры published методов, сопоставляя методы с событиями с RTTI, которые ссылались на этот метод в run-time. Как я кратко упомянул в моём предыдущем посте, David Glassborow указал мне на расширенный RTTI, который появился в Delphi 6.

среда, 27 июля 2011 г.

RTTI классов

Это перевод Class RTTI. Автор: David Glassborow.

Этот пост является продолжением моего предыдущего поста, который говорил про RTTI интерфейсов в Delphi и был вдохновлён серией постов Hallvard-а по RTTI. Этот пост рассказывает о некоторых продвинутых возможностях RTTI для классов, описания которых я больше нигде не видел.

вторник, 26 июля 2011 г.

RTTI интерфейсов

Это перевод Interface RTTI. Автор: David Glassborow.

Чтение этой статьи Hallvard-а по RTTI и её дополнения вдохновило меня собрать вместе несколько постов о двух связанных частях RTTI в Delphi. В частности, это был один из комментариев в блоге Hallvard-а по использованию RTTI для вызова методов объектов в манере позднего связывания. Этот и следующие посты покроют использование продвинутой RTTI информации, описание которого я нигде больше не видел. Этот пост опишет некоторые возможности мета-данных интерфейсов, а следующий расскажет о более богатом классовом RTTI для методов.

понедельник, 25 июля 2011 г.

Детали реализации published полей

Это перевод Published fields details. Автор: Hallvard Vassbotn.

В предыдущей статье мы посмотрели на то, как published поля используются IDE и VCL, чтобы сделать простыми работу с компонентными ссылками и нахождение классовых ссылок по именам типов. Сейчас мы заглянем глубже в детали реализации published полей.

воскресенье, 24 июля 2011 г.

Published поля

Это перевод Published fields. Автор: Hallvard Vassbotn.

В нашей небольшой серии по обратной разработке (reverse engineering) недокументированных полей VMT классов Delphi, мы видели поле FieldTable. Это поле указывает на структуры, которые описывают published поля класса. В Delphi published поля должны быть ссылками на объекты и в основном используются формами (form) и модулями данных (datamodule) для хранения ссылок на свои компоненты в логически именованных полях для удобства доступа (потому что альтернативой к полям является использование массива Components, что включает в себя поиск и преобразования типов).

суббота, 23 июля 2011 г.

Хак №10: получение параметров published методов

Это перевод Hack #10: Getting the parameters of published methods. Автор: Hallvard Vassbotn.

Этот хак не очень полезен на практике, он был сделан под вдохновением от комментария к посту о published методах. Тогда я начал расследование, как это можно сделать. Вспомните, что компилятор сейчас не кодирует сигнатуру метода в RTTI для published методов - сохраняются только адрес и имя метода.

Так что с первого взгляда кажется, что получить эту информацию - невозможно. Но давайте сделаем шаг назад и подумаем о том, как IDE обрабатывает события и published методы в design-time. Если у вас уже объявлено несколько обработчиков событий (реализованных в нескольких published методах формы), то инспектор объектов отфильтрует их и покажет только те методы (в выпадающем списке), сигнатура которых совместима с событием. Как IDE узнаёт, какие методы нужно показывать в списке, а какие - нет?

пятница, 22 июля 2011 г.

Под капотом published методов

Это перевод Under the hood of published methods. Автор: Hallvard Vassbotn.

Теперь, когда я рассказал, что такое published методы, как IDE и VCL используют их при сохранении/загрузке .DFM и как использовать их полиморфно, мы готовы погрузиться глубже в их детали реализации под капотом языка.

среда, 20 июля 2011 г.

Получение списка реализуемых интерфейсов

Это перевод Getting a list of implemented interfaces. Автор: Hallvard Vassbotn.

Френк задал такой вопрос:
Есть ли какой-нибудь способ узнать, какие интерфейсы (список интерфейсов) поддерживает определённый компонент (я не знаю интерфейсы, так что не могу запросить у него конкретные интерфейсы)?
Да, способ есть.

вторник, 19 июля 2011 г.

Published методы

Это перевод Published methods. Автор: Hallvard Vassbotn.

Обычно о них не думают как о возможностях объектно-ориентированного программирования, но published методы основаны на RTTI, чтобы можно было выполнять поиск методов, используя строку с именем метода, во время выполнения (run-time). Эта возможность широко используется IDE и VCL при написании обработчиков событий во время разработки.

понедельник, 18 июля 2011 г.

Хак №9: структура таблицы динамических методов

Это перевод Hack #9: Dynamic method table structure. Автор: Hallvard Vassbotn.

Один из слотов в магической структуре компилятора из классовой виртуальной таблицы методов (VMT) является указателем на динамическую таблицу методов (DMT) этого же класса. Класс имеет DMT, только если он объявляет или перекрывает один или несколько динамических методов (или методов-сообщений). DMT содержит 16-разрядный (word) Count, за которым следует массив [0.. Count-1] of Smallint индексов и массив [0..Count-1] of Pointer, содержащий адреса кода реализации динамических методов. Обратите внимание, что массивы "встроены" в структуру DMT (в ней нет указателей на эти массивы).

воскресенье, 17 июля 2011 г.

Реализация динамических методов компилятором

Это перевод Dynamic methods compiler implementation. Автор: Hallvard Vassbotn.

В предыдущей статье мы рассмотрели как компилятор реализует вызовы не виртуальных и виртуальных методов. Мы также обсудили обоснование и семантику динамических методов. Как вы помните, динамические методы работают так же, как и виртуальные методы, только медленнее. В этой статье мы зароемся в магию компилятора и поддержку RTL, которые используются для поддержки динамических методов. Отметим, что большая часть механики, используемой для динамических методов, используется также для методов-сообщений (message methods) - с той лишь разницей, что методы-сообщений позволяют программисту указывать индекс метода (он же - номер сообщения, положительное 16-разрядное число).

суббота, 16 июля 2011 г.

Динамические методы и inherited

Это перевод Dynamic methods and inherited. Автор: Hallvard Vassbotn.

В предыдущем сообщении блога мы рассмотрели, как работают виртуальные методы и вызовы унаследованных методов. В Delphi есть и другой вид полиморфных методов: динамические методы (dynamic methods). Заметим, что эта серия постов про полиморфизм говорит только про Native Win32, но достаточно упомянуть, что в Delphi для .NET динамические методы, на самом деле, идентичны виртуальным методам. В Win32 методы сообщений (message methods) используют те же базовые структуры компилятора и механизм диспетчеризации, что и динамические методы, в то время как в .NET используется решение на базе атрибутов и отражения (reflection). Мы рассмотрим методы сообщений в следующем посте.

пятница, 15 июля 2011 г.

Хак №8: явные вызовы VMT

Это перевод Hack #8: Explicit VMT calls. Автор: Hallvard Vassbotn.

Чтобы приспособить двоичный протокол COM в до-интерфейсной эпохе Delphi 2, все определяемые пользователем виртуальные методы имели положительные смещения VMT. Это также означает, что виртуальные методы, определенные самим TObject, имеют отрицательные смещения VMT. Кроме того, VMT также содержит ряд "магических" полей для поддержки таких возможностей, как ссылки на родительский класс, получение имени класса, таблицы динамических методов, таблицы опубликованных (published) методов, таблицы RTTI, таблицы инициализации волшебных полей, (устаревшей) таблицы OLE Automation и таблицы реализованных интерфейсов.

четверг, 14 июля 2011 г.

Реализация вызовов методов компилятором

Это перевод Method calls compiler implementation. Автор: Hallvard Vassbotn.

Чтобы поддерживать множество возможностей языка, компилятор Delphi использует несколько различных структур данных и шаблонов генерации машинного кода. Чтобы помочь в понимании того, как реализуются компилятором возможности языка Delphi, чтобы было проще опознавать эти шаблоны и структуры при низкоуровневой отладке ассемблерного кода и чтобы было возможным понимать, что вы делаете при патчинге кода в run-time - я расскажу про некоторые из этих шаблонов в этом посте.

среда, 13 июля 2011 г.

Виртуальные методы и inherited

Это перевод Virtual methods and inherited. Автор: Hallvard Vassbotn.

Delphi имеет необычно богатую языковую поддержку полиморфного поведения. Самая простая и базовая, которую большинство программистов ассоциируют с полиморфизмом, - это виртуальные методы.

вторник, 12 июля 2011 г.

Полиморфизм ad nauseum

Это перевод Polymorphism ad nauseum. Автор: Hallvard Vassbotn.

Как и все объектно-ориентированные языки, Delphi (Object Pascal) поддерживает концепцию полиморфизма. Полиморфизм - это греческое слово, буквально означающее "много форм". В применении к программированию это слово означает идею, что вызов концептуальной операции отделён от её реальной реализации. Фактически, в run-time эта реализация может существенно меняться, в зависимости от типа объекта, выполняющего операцию.