Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.05.2024, 19:04   #1
killzone
 
Регистрация: 25.03.2010
Сообщений: 8
По умолчанию Двойное разыменовывание??? Код рабочий, но не понимаю как работает.

Приветствую уважаемые форумчане!
Привожу рабочий код. Но не понимаю как это всё работает, я раньше не встречал символ двойного разыменовывания ^^. Нашел в интернете такую функцию.
Код:
type
TNotifyReference = reference to procedure(Sender: TObject);

function Proc2NotifyEvent(const aProc: TNotifyReference): TNotifyEvent;
type
  TVtable = array[0..3] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  TMethod(Result).Code := PPVtable((@aProc)^)^^[3];
  TMethod(Result).Data := Pointer((@aProc)^);
end;
Я эту функцию использую для присвоения кнопке на событие OnClick анонимную процедуру:
Код:
Form_GridClient.Button_SelectAll.OnClick := Proc2NotifyEvent(
    procedure (Sender:TObject)
    begin
      showmessage('Я работаю, всё ок!');
    end);
Всё отлично работает, но хочу понять что вообще происходит внутри этой функции и как называется эта операция ^^?
killzone вне форума Ответить с цитированием
Старый 09.05.2024, 22:01   #2
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,799
По умолчанию

Разыменование — одноместная операция, применяемая к аргументу слева. Несколько операций подряд дают множественное разыменование, по числу знаков: двойное, тройное, и так далее.

Процедура основана на знании внутренних структур типов, генерируемых компилятором. Тип TMethod описан так:
Код:
type
  TMethod = record
    Code, Data: Pointer;
  end;
Есть и теория по разным типам ссылок на процедуры. Она должна быть описана в справке.
Vapaamies вне форума Ответить с цитированием
Старый 10.05.2024, 06:40   #3
killzone
 
Регистрация: 25.03.2010
Сообщений: 8
По умолчанию

Спасибо за статью, в голове начинает проясняться.
Значит я конвертирую анонимную процедуру в метод. Хотя наверно слово "конвертирую" тут не подходит, я создаю метод из анонимной процедуры.
PPVtable это адрес в памяти, по которому находится адрес в памяти по которому находится виртуальная таблица (методов?) (TVtable состоящая из 4х указателей). Проще говоря PPVtable это указатель на указатель на виртуальную таблицу. Отсюда и идут подряд операции разыменовывания ^^ чтобы добраться до виртуальной таблицы без промежуточных переменных. Это вроде понятно.
В строчке
Код:
 TMethod(Result).Data := Pointer((@aProc)^);
мы показываем начало анонимной процедуры, а вот в строчке
Код:
TMethod(Result).Code := PPVtable((@aProc)^)^^[3];
мы показываем 4й (начинаем с 0) указатель из виртуальной таблицы.
Вот тут не понимаю почему [3]? Что является [0], [1], [2], [3]. У нас что [0] это будет адрес начала анонимной процедуры, [1] это адрес Sender:TObject?, [2] - это ... of object? Тут в общем запутался...



В строчке
Код:
 TMethod(Result).Data := Pointer((@aProc)^);
Мы показываем Sender:TObject.

А вот в строчке
Код:
TMethod(Result).Code := PPVtable((@aProc)^)^^[3];
Мы показываем тело анонимной процедуры. [0] - это QueryInterface, [1] - AddRef, [2] - Release [3] - MyAnonymousProcedure? Верно?

Последний раз редактировалось killzone; 10.05.2024 в 06:56.
killzone вне форума Ответить с цитированием
Старый 10.05.2024, 10:01   #4
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,799
По умолчанию

Цитата:
Сообщение от killzone Посмотреть сообщение
Мы показываем тело анонимной процедуры. [0] - это QueryInterface, [1] - AddRef, [2] - Release [3] - MyAnonymousProcedure? Верно?
Отладчик у тебя перед глазами, не у меня. Я сам не пишу на модных версиях Delphi, так что не знаю, как оно там внутри. Могу предложить включить в настройках генерацию map-файла с номерами строк (Detailed), а потом посмотреть по адресам. Возможно, в отладочной сборке придется также отключить ASLR (dynamic image base), если не отключено по умолчанию.
Vapaamies вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не понимаю как работает CALL Bizunov SQL, базы данных 0 04.06.2013 11:29
Что то не понимаю как этот код работает? Denis19061989 Помощь студентам 0 26.05.2013 10:33
Не работает рабочий код при навеске на другой контрол samouelson C# (си шарп) 3 21.06.2012 20:25
Разыменовывание итератора litviak Общие вопросы C/C++ 5 08.06.2012 14:29
Вирус,из-за которого не работает рабочий стол JerryS Безопасность, Шифрование 7 13.09.2009 19:54