Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  00:31[Войти] | [Зарегистрироваться]
Ответ на вопрос № 41069

25-03-2006 23:34
Доброго времени суток, уважаемые жители королевства.

Втал жестко такой вопрос из области RTTI:

Необходимо определить тип published метода класса, для того, чтобы его корректно вызвать.
(Со свойствами все понятно - через PPropList[i].PropType, а вот с методами... То есть не со свойствами типа метод (событиями) tkMethod, а именно с методами)

например

type

  TSimpleMethod = procedure of object;
  TIntMethod = procedure(Value: integer) of object;

  TMyClass = class(TPersistent)
  publised 
    procedure Foo;
    procedure Foo2(Value: integer);
  end;

  Теперь хочется программно определить имея TMyClass, что Foo относится к TSimpleMethod, а Foo2 - к TIntMethod;

Пишем:

procedure DoIt(AClass: TClass; MethodName: string); 
// сюда передаем TMyClass и соотвественно 'Foo' или 'Foo2'
var
  M: TMethod;
  Simple: TSimpleMethod;
  IntProc: TIntMethod;

begin
  M.Code := AClass.MethodAddress(MethodName);

  if ??????? then
  begin
    Simple := TSimpleMethod(M);
    if Assigned(M) then
      Simple;                  // вызываем метод Foo;
  end
  else
  if ??????? then
  begin
    IntProc := TIntMethod(M);
    if Assigned(IntProc) then
      IntProc(5);              // вызываем метод Foo2(5);
  end;
end;

Вот и вопрос: что должно стоять на месте "??????" (не в смысле MethodName = 'Foo' конечно, а через какие-то тропы M.Code.)

Иными словами как удостовериться, что AClass.MethodAddress('Foo') совместим с TSimpleMethod, а AClass.MethodAddress('Foo2') совместим с TIntMethod.

У TMethod есть еще свойство Data: Pointer но я так и не смог разобраться, что в этом свойстве находится и как это использовать. Может быть тут какая-то собака порылась.

Не могли бы просветить? 

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

31-03-2006 07:07 | Сообщение от автора вопроса
GoldFinch, смелое решение!
А кто такой Self?

30-03-2006 14:35
???? == self is TSimpleMethod

30-03-2006 12:42
Ну загляните в ObjAuto.pas там же есть все структуры. Вот информация о параметре:

TParamInfo = packed record
    Flags: TParamFlags;
    ParamType: ^PTypeInfo;
    Access: Word;
    Name: ShortString;
  end;


Смысл всех полей ясен из названия, может кроме Access который задаёт расположение параметра на стеке или в регистрах. Поизучайте код из ObjAuto.pas, если вам нужно просто вызвать метод так можно ObjectInvoke использовать, а не лезть в слабо документированные глубины RTTI.

30-03-2006 10:19 | Сообщение от автора вопроса
Да! {$METHODINFO ON} - это то что надо!

правда есть еще некоторые неясности.

смотрим Class.vmtMethodTable,
беглый просмотр дал следующие результаты:

два байта - число методов
далее методы в следующем формате
(привожу для функции   
TTest = class
...
published
  function DoIt(Param1: TObject; Param2: Integer; P3: TTest): Integer;
end;
)



Длина  Адресс   
текущ.  кода
записи  методоа    Имя метода

E  .  T  N  E  .  .  D  o  I  t
45 00 54 4E 45 00 04 44 6F 49 74

      Указатель на
      PTypeInfo
?????  результата

.  .  <  .  @  . 
01 00 3C 10 40 00

        Указатель на     
        PTypeInfo          ну это понятно
        данного            что, но не понятно
???????? класса      ?????  зачем...

.  .  .  .  U  E  .  .  .  .  S  e  l  f 

0C 00 00 DC 45 45 00 00 00 04 53 65 6C 66

  Указатель на
  PTypeInfo
  первого            Имя первого 
?? параметра  ?????  параметра ф-ции

.  o  .  @  .  .  .  .  P  a  r  a  m  1 
00 F4 10 40 00 01 00 06 50 61 72 61 6D 31

  Указатель на
  PTypeInfo
  второго            Имя второго 
?? параметра  ?????  параметра ф-ции

.  <  .  @  .  .  .  .  P  a  r  a  m  2 
00 3C 10 40 00 02 00 06 50 61 72 61 6D 32

  Указатель на
  PTypeInfo
  третьего          Имя третьего
?? параметра  ?????  параметра

.  U  E  E  .  .  .  .  P  3
00 DC 45 45 00 08 00 02 50 33



DRON, не знаете ли вы, что содержится в областях обозначенных как "????" ?

26-03-2006 04:21
Для включения генерации RTTI для методов используется "секретная" директива "{$METHODINFO ON}", а вызов таких методов можно делать с помощью ObjectInvoke. Ну и функция GetMethodInfo пригодится. Всё это находится в модуле ObjAuto.pas Присутствует данная возможность начиная с Delphi7 (а может и 6), но её описание в справке вы не найдёте.

26-03-2006 03:02
Даже не знаю, TMethod объявлен как Record, а для рекордов RTTI, насколько я понимаю, не генерится

26-03-2006 02:44 | Сообщение от автора вопроса
Да я это тоже видел.

Только вот как получить TypeData для метода???

(Не для property типа метод, а для метода (по указателю на него или имени))

P.S. Про TMetod.Data - я что-то в своем вопросе сморозил. Там ведь Self должен лежать. Затмение рассудка. :)

26-03-2006 02:19
Пробежался глазами по TypInfo.pas и нашел следующее, может пригодится:

TMethodKind = (mkProcedure, mkFunction, mkConstructor, mkDestructor,
    mkClassProcedure, mkClassFunction,
    { Obsolete }
    mkSafeProcedure, mkSafeFunction);

TTypeData = packed record
    case TTypeKind of
...
    tkMethod: (
        MethodKind: TMethodKind;
        ParamCount: Byte;
        ParamList: array[0..1023] of Char)

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Кто съел Красную шапочку?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования