Это перевод Why does my command line redirection echo with an extra 1? Who’s inserting these rogue 1s everywhere? Автор: Реймонд Чен.
Если вы оставите включённым режим echo в командном файле, и командный файл выполняет команду с перенаправлением, тогда в выводе появится загадочная единичка.
...when altering one's mind becomes as easy as programming a computer, what does it mean to be human?..
Показаны сообщения с ярлыком хак. Показать все сообщения
Показаны сообщения с ярлыком хак. Показать все сообщения
вторник, 17 ноября 2020 г.
четверг, 20 апреля 2017 г.
Как создать "сигнальные" значения для указателей в Windows
Это перевод On generating sentinel pointer values in Windows. Автор: Реймонд Чен.
Предположим, что вам нужно несколько т.н. "сигнальных" значений. К примеру, пусть ваша функция работает с указателями на тип Widget, а вам требуется способ передавать значения с особым смыслом, к примеру: "Не указан Widget", или "Используй значение по умолчанию", или "Возьми Widget из родительского объекта", или "Все известные Widget-ы".
Предположим, что вам нужно несколько т.н. "сигнальных" значений. К примеру, пусть ваша функция работает с указателями на тип Widget, а вам требуется способ передавать значения с особым смыслом, к примеру: "Не указан Widget", или "Используй значение по умолчанию", или "Возьми Widget из родительского объекта", или "Все известные Widget-ы".
вторник, 7 июня 2016 г.
Наконец-то я прошёл эту клёвую игру - Photoshop, сейчас я тебе пришлю видео
Это перевод I finally finished this awesome game called Photoshop, let me send you a video. Автор: Реймонд Чен.
Раньше, чтобы записать видео работы программы на PC, вам требовалась какая-то сторонняя программа. Но теперь эта возможность встроена в Windows 10 (в предположении, что вы не против сыграть в ролевую игру).
Раньше, чтобы записать видео работы программы на PC, вам требовалась какая-то сторонняя программа. Но теперь эта возможность встроена в Windows 10 (в предположении, что вы не против сыграть в ролевую игру).
понедельник, 8 августа 2011 г.
Хак №15: замещение динамических и message-методов в run-time
Это перевод Hack#15: Overriding message and dynamic methods at run-time. Автор: Hallvard Vassbotn.
В прошлый раз мы посмотрели на способ полной замены класса. Как мы говорили, у этой техники есть несколько проблем. Но есть много способов снять шкуру с кошки (извините, любители кошек!), и в нашем случае (исправление мерцания
В прошлый раз мы посмотрели на способ полной замены класса. Как мы говорили, у этой техники есть несколько проблем. Но есть много способов снять шкуру с кошки (извините, любители кошек!), и в нашем случае (исправление мерцания
TProgressBar без изменения интерфейса этого класса) есть как минимум три других решения.воскресенье, 7 августа 2011 г.
Хак №14: изменение класса объекта в run-time
Это перевод Hack#14: Changing the class of an object at run-time. Автор: Hallvard Vassbotn.
Иногда (вроде, когда вам по той или иной причине нужно сохранить обратную совместимость с бинарным dcu) вам может быть необходимым использовать хак или два. Один такой хак заключается в изменении класса объекта в run-time. К примеру, это может понадобится для изменения виртуального, динамического или message-метода.
Иногда (вроде, когда вам по той или иной причине нужно сохранить обратную совместимость с бинарным dcu) вам может быть необходимым использовать хак или два. Один такой хак заключается в изменении класса объекта в run-time. К примеру, это может понадобится для изменения виртуального, динамического или message-метода.
суббота, 6 августа 2011 г.
Анализ хака добавления "published" свойства без изменения класса
Это перевод Review: Delphi 2007 for Win32 (Beta) - part three. Автор: Hallvard Vassbotn.
Прим.пер.: в оригинале это была серия из трёх статей по обзору нововведений в Delphi 2007. Я оставил лишь одну часть, которая говорит не столько про нововведения, сколько про хаки - как часть серии "Хак №X".
В VCL (а равно и в RTL) появилось несколько исправлений багов, но мы не будем их рассматривать. Хотя Delphi 2007 остаётся совместимой с бинарными .dcu файлами предыдущей версии Delphi, CodeGear, тем не менее, удалось добавить новую функциональность и даже новые свойства в существующий класс
Прим.пер.: в оригинале это была серия из трёх статей по обзору нововведений в Delphi 2007. Я оставил лишь одну часть, которая говорит не столько про нововведения, сколько про хаки - как часть серии "Хак №X".
В VCL (а равно и в RTL) появилось несколько исправлений багов, но мы не будем их рассматривать. Хотя Delphi 2007 остаётся совместимой с бинарными .dcu файлами предыдущей версии Delphi, CodeGear, тем не менее, удалось добавить новую функциональность и даже новые свойства в существующий класс
TCustomForm. Как они это сделали?пятница, 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”.
Так как же мы сделали это?
Во-первых, если вы пурист ООП или фреймворков и имеете слабый желудок - лучше закройте эту страницу прямо сейчас.
В ожидаемом релизе 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”.
Так как же мы сделали это?
четверг, 4 августа 2011 г.
Недокументированный CreateProcess
Это перевод Undocumented CreateProcess. Автор: James Brown.
Прим.пер.: эта статья была написана относительно давно. Некоторые возможности, упомянутые в ней, с тех пор стали документированы. В этом случае я заменил придуманные автором имена на те, которые сейчас используются в документации MSDN. И в любом случае, стандартное предупреждение - использовать хаки только как последнее средство.
Этот мануал является частью новой серии, которая будет сосредоточена на некоторых не-GUI вопросах, связанных с программированием в Windows. Предметом этого мануала будет Win32 API функция
Прим.пер.: эта статья была написана относительно давно. Некоторые возможности, упомянутые в ней, с тех пор стали документированы. В этом случае я заменил придуманные автором имена на те, которые сейчас используются в документации MSDN. И в любом случае, стандартное предупреждение - использовать хаки только как последнее средство.
Этот мануал является частью новой серии, которая будет сосредоточена на некоторых не-GUI вопросах, связанных с программированием в Windows. Предметом этого мануала будет Win32 API функция
CreateProcess. Эта статья разделена на несколько секций, каждая из которых описывает приятный факт о CreateProcess, который можно использовать в своих интересах. То, что я буду описывать, нельзя найти в документации Microsoft, но эти вещи были обнаружены многими людьми на протяжении многих лет путём множества экспериментов. Вся информация, собранная здесь, была найдена в различных источниках - особенно в старых публикациях таких изданий, как "Windows Developer Journal", начиная с середины 90-х годов, а также старых сообщениях USENET.среда, 3 августа 2011 г.
Хак №13: более быстрый доступ к глобальным данным ($ImportedData)
Это перевод Hack#13: Access globals faster ($ImportedData). Автор: Hallvard Vassbotn.
Вокруг пакетов времени выполнения Delphi (run-time packages) всегда была волшебная аура. Пакеты позволяют вам разделять Delphi код на более высоком уровне, чем это доступно с простыми DLL. Написание API библиотеки DLL включает в себя создание кучи плоских глобальных функций (анти-ООП) и избегание любых типов данных, хоть отдалённо сложнее Integer, Double, статических массивов, PChar и записей. Вы не можете обмениваться классами, объектами, глобальными переменными, не говоря уже про простые строки (если только и клиент и сервер не собраны в одной и той же версии Delphi и оба используют общий менеджер памяти).
Вокруг пакетов времени выполнения Delphi (run-time packages) всегда была волшебная аура. Пакеты позволяют вам разделять Delphi код на более высоком уровне, чем это доступно с простыми DLL. Написание API библиотеки DLL включает в себя создание кучи плоских глобальных функций (анти-ООП) и избегание любых типов данных, хоть отдалённо сложнее Integer, Double, статических массивов, PChar и записей. Вы не можете обмениваться классами, объектами, глобальными переменными, не говоря уже про простые строки (если только и клиент и сервер не собраны в одной и той же версии Delphi и оба используют общий менеджер памяти).
вторник, 2 августа 2011 г.
Хак №12: создаём меньшие .exe файлы ($SetPEFlags)
Это перевод Hack#12: Create smaller .EXE files ($SetPEFlags). Автор: Hallvard Vassbotn.
Нет, этот пост - не про так называемые EXE-компрессоры: я не верю в их пользу. И это не чистый хак - мы не нарушаем никаких правил, это просто документирование слабо известной возможности Delphi 2006 (она не реализована в D7, и я ничего не знаю насчёт Delphi 2005, поскольку она давно у меня не стоит).
Нет, этот пост - не про так называемые EXE-компрессоры: я не верю в их пользу. И это не чистый хак - мы не нарушаем никаких правил, это просто документирование слабо известной возможности Delphi 2006 (она не реализована в D7, и я ничего не знаю насчёт Delphi 2005, поскольку она давно у меня не стоит).
понедельник, 1 августа 2011 г.
Хак №11: получение GUID интерфейса по интерфейсной ссылке
Это перевод Hack#11: Get the GUID of an interface reference. Автор: Hallvard Vassbotn.
Недавно Randy Magruder обратился ко мне с одним своим очень интересным проектом, над которым он работает:
Недавно Randy Magruder обратился ко мне с одним своим очень интересным проектом, над которым он работает:
Что я пытаюсь сделать: добавлять и удалять поддерживаемые интерфейсы в класс в run-time и вызывать их. Я уже сделал достаточно, чтобы я мог использовать модель OTAServices model из Delphi для передачи дополнительных интерфейсов, добавления их во внутренний список, и заместил поведение QueryInterface, чтобы вызов возвращал интерфейс из списка, вместо стандартной таблицы объекта.
Это звучит как клёвый (и сложный) проект! Он продолжает:
Но если вызывающий объекта знает только GUID интерфейса, который ему нужен, и хочет получить подходящий интерфейс и вызвать метод в нём по имени, то что я могу с этим сделать? Мне использовать расширенный RTTI с IInvoker?
Ну, я не уверен, как это можно решить. AFAIK, не существует простого проецирования от объекта, реализующего интерфейс, к информации типа этого интерфейса. Одно из решений может заключаться в реализации проецирования GUID интерфейсов на информацию типа.
И ещё: ты случайно не знаешь способ извлечения GUID интерфейса в run-time, ...Это должно быть возможным, хотя и немного сложновато.
воскресенье, 31 июля 2011 г.
Расширенная RTTI информация классов
Это перевод Extended Class RTTI. Автор: Hallvard Vassbotn.
Как я упоминал ранее, Delphi (начиная с версии 7) поддерживает генерацию расширенной RTTI информации о методах класса - через компиляцию класса в режиме
Я сумел написать свои собственные определения и подпрограммы, которые выдёргивают и сохраняют расширенную RTTI информацию классов в формат, удобный для внешнего использования. Как обычно, моё тестовое приложение будет дампить тестовый класс, воссоздавая его псевдо-объявление.
Как я упоминал ранее, 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 информацию, его нужно собрать в режиме
Чтобы поддерживать базовые механизмы 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 информации для всех интерфейсов, но она не включает (не генерирует) информацию о методах для "нормальных" интерфейсов:
Delphi поддерживает получение RTTI информации для всех интерфейсов, но она не включает (не генерирует) информацию о методах для "нормальных" интерфейсов:
type
{$M-}
IMyMMInterface = interface
procedure Foo;
end;
понедельник, 25 июля 2011 г.
Детали реализации published полей
Это перевод Published fields details. Автор: Hallvard Vassbotn.
В предыдущей статье мы посмотрели на то, как published поля используются IDE и VCL, чтобы сделать простыми работу с компонентными ссылками и нахождение классовых ссылок по именам типов. Сейчас мы заглянем глубже в детали реализации published полей.
В предыдущей статье мы посмотрели на то, как published поля используются IDE и VCL, чтобы сделать простыми работу с компонентными ссылками и нахождение классовых ссылок по именам типов. Сейчас мы заглянем глубже в детали реализации published полей.
суббота, 23 июля 2011 г.
Хак №10: получение параметров published методов
Это перевод Hack #10: Getting the parameters of published methods. Автор: Hallvard Vassbotn.
Этот хак не очень полезен на практике, он был сделан под вдохновением от комментария к посту о published методах. Тогда я начал расследование, как это можно сделать. Вспомните, что компилятор сейчас не кодирует сигнатуру метода в RTTI для published методов - сохраняются только адрес и имя метода.
Так что с первого взгляда кажется, что получить эту информацию - невозможно. Но давайте сделаем шаг назад и подумаем о том, как IDE обрабатывает события и published методы в design-time. Если у вас уже объявлено несколько обработчиков событий (реализованных в нескольких published методах формы), то инспектор объектов отфильтрует их и покажет только те методы (в выпадающем списке), сигнатура которых совместима с событием. Как IDE узнаёт, какие методы нужно показывать в списке, а какие - нет?
Этот хак не очень полезен на практике, он был сделан под вдохновением от комментария к посту о published методах. Тогда я начал расследование, как это можно сделать. Вспомните, что компилятор сейчас не кодирует сигнатуру метода в RTTI для published методов - сохраняются только адрес и имя метода.
Так что с первого взгляда кажется, что получить эту информацию - невозможно. Но давайте сделаем шаг назад и подумаем о том, как IDE обрабатывает события и published методы в design-time. Если у вас уже объявлено несколько обработчиков событий (реализованных в нескольких published методах формы), то инспектор объектов отфильтрует их и покажет только те методы (в выпадающем списке), сигнатура которых совместима с событием. Как IDE узнаёт, какие методы нужно показывать в списке, а какие - нет?
пятница, 22 июля 2011 г.
Под капотом published методов
Это перевод Under the hood of published methods. Автор: Hallvard Vassbotn.
Теперь, когда я рассказал, что такое published методы, как IDE и VCL используют их при сохранении/загрузке .DFM и как использовать их полиморфно, мы готовы погрузиться глубже в их детали реализации под капотом языка.
Теперь, когда я рассказал, что такое published методы, как IDE и VCL используют их при сохранении/загрузке .DFM и как использовать их полиморфно, мы готовы погрузиться глубже в их детали реализации под капотом языка.
четверг, 21 июля 2011 г.
Чистые интерфейсы в Delphi
Это перевод Pure interfaces in Delphi. Автор: Hallvard Vassbotn.
В комментарии к последнему посту Huseyn спросил:
В комментарии к последнему посту Huseyn спросил:
В Delphi все интерфейсы являются наследникамиДа, это верно, что в Delphi создание интерфейса всегда подразумевает неявное наследование отIUnknown(илиIInterface- Hallvard Vassbotn), но в мире C есть ещё более базовая сущность - интерфейсы, не являющиеся наследникамиIUnknown. Я встретил такой интерфейс в одной DLL, которую мне надо было использовать. Но я не могу это сделать в Delphi.
IUnknown или IInterface (два имени для отличий COM и Delphi интерфейсов). И это означает, что все интерфейсы в Delphi будут иметь три метода QueryInterface, _AddRef и _Release. Это, конечно, делает сложным (или невозможным) реализацию чистого интерфейса из не-COM DLL с использованием синтаксиса объявления интерфейсов в Delphi.вторник, 19 июля 2011 г.
Published методы
Это перевод Published methods. Автор: Hallvard Vassbotn.
Обычно о них не думают как о возможностях объектно-ориентированного программирования, но published методы основаны на RTTI, чтобы можно было выполнять поиск методов, используя строку с именем метода, во время выполнения (run-time). Эта возможность широко используется IDE и VCL при написании обработчиков событий во время разработки.
Обычно о них не думают как о возможностях объектно-ориентированного программирования, но published методы основаны на RTTI, чтобы можно было выполнять поиск методов, используя строку с именем метода, во время выполнения (run-time). Эта возможность широко используется IDE и VCL при написании обработчиков событий во время разработки.
понедельник, 18 июля 2011 г.
Хак №9: структура таблицы динамических методов
Это перевод Hack #9: Dynamic method table structure. Автор: Hallvard Vassbotn.
Один из слотов в магической структуре компилятора из классовой виртуальной таблицы методов (VMT) является указателем на динамическую таблицу методов (DMT) этого же класса. Класс имеет DMT, только если он объявляет или перекрывает один или несколько динамических методов (или методов-сообщений). DMT содержит 16-разрядный (
Один из слотов в магической структуре компилятора из классовой виртуальной таблицы методов (VMT) является указателем на динамическую таблицу методов (DMT) этого же класса. Класс имеет DMT, только если он объявляет или перекрывает один или несколько динамических методов (или методов-сообщений). DMT содержит 16-разрядный (
word) Count, за которым следует массив [0.. Count-1] of Smallint индексов и массив [0..Count-1] of Pointer, содержащий адреса кода реализации динамических методов. Обратите внимание, что массивы "встроены" в структуру DMT (в ней нет указателей на эти массивы).
Подписаться на:
Сообщения (Atom)