Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как узнать имя вызвавшей процедуры. 
:(
    Опции темы
LamerTM
Дата 16.5.2009, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



Есть процедура (допустим называется WL), которую вызывают другие процедуры. Хочется из процедуры WL узнавать имя процедуры ее вызвавшей (без передачи ей каких-то дополнительных параметров). Это возможно ?
PM MAIL   Вверх
CodeMonkey
Дата 16.5.2009, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89





--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
LamerTM
Дата 16.5.2009, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



Цитата(CodeMonkey @ 16.5.2009,  16:04)
Оно?

Нет. У меня другой случай.


У меня так:


Код

type 

TGen = сlass
 procedure wl(s: string);
end;

TSec1 = сlass(TGen)
procedure Proc1;
end;

TSec2 = сlass(TGen)
procedure Procedure2;
end;

implementation

procedure TSec1.Proc1;
begin
wl('text1');
end;

procedure TSec2.Procedure2;
begin
wl('text2');
end;

procedure TGen.wl(s: string);
begin
 // вот в этом месте хотелось бы получить название процедуры, которая вызвала wl, чтобы преобразовать строку s таким образом, например: "Procedure2: text2"
end;


Для чего мне это вообще понадобилось. Я хочу сделать чтобы моя программа писала лог. Разные процедуры передают сообщения в процедуру wl в виде строк (wl пишет эти сообщения в окно либо в log-файл). Хотелось бы чтобы wl сама вычисляла имя процедуры, которая эту сроку передала, чтобы знать какая именно процедура это сообщение генерировала. Имя класса у меня уже вычисляется (по ClassName). А имя процедуры нет. Можно передавать имя процедуры прямо в строке. Но мне хочется чтобы само вычислялось.
PM MAIL   Вверх
CodeMonkey
Дата 16.5.2009, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



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

Решение в общем виде выглядит так: вы подключаете в программу отладочную информацию и извлекаете имя из неё. Один из вариантов - используя JCL и JclDebug.
Вот ссылка для чтения:

http://forum.vingrad.ru/index.php?showtopi...t&p=1696161

В JclDebug вас будут интересовать функции Caller и GetLocationInfo(Str)

Если вы в своей программе используете какой-либо трейсер исключений (EurekaLog, madExcept или аналоги) - то, конечно, лучше бы воспользоваться его функциями. Например, в EurekaLog есть GetSourceInfoByAddr.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
LamerTM
Дата 16.5.2009, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



Цитата(CodeMonkey @ 16.5.2009,  16:50)
По-умолчанию, в общем случае, этого сделать нельзя. Вы можете узнать только адрес вызывающего. Его имя же нигде в программе не хранится. Исключение составляет RTTI классов, но это решение очень узко-специализированное.

Решение в общем виде выглядит так: вы подключаете в программу отладочную информацию и извлекаете имя из неё. Один из вариантов - используя JCL и JclDebug.
Вот ссылка для чтения:

http://forum.vingrad.ru/index.php?showtopi...t&p=1696161

В JclDebug вас будут интересовать функции Caller и GetLocationInfo(Str)

Если вы в своей программе используете какой-либо трейсер исключений (EurekaLog, madExcept или аналоги) - то, конечно, лучше бы воспользоваться его функциями. Например, в EurekaLog есть GetSourceInfoByAddr.

ОК, там много чего читать, поэтому я пока еще один вопрос задам.

Имея адрес процедуры можно узнать ее имя функцией MethodName. В данном случае мне этого достаточно, т.к. у меня везде классы. Я так когда-то делал обработчик исключительных ситуаций. Но он получал информацию из объекта Exception, который содержал адрес исключения ExceptionAddress. По этому адресу определялась процедура в которой произошло исключение.

А сейчас адреса нет. Но по идее адрес вызывающей процедуры должен оставаться где-то в стеке (вернее адрес места вызова процедуры wl). Как-нибудь можно из стека этот адрес получить? Если получится, то имя процедуры вычислить будет несложно. Это будет самое лучшее решение для меня, т.к. самое простое.
PM MAIL   Вверх
CodeMonkey
Дата 16.5.2009, 18:32 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Вот один из возможных вариантов:

Код
type
  PStackFrame = ^TStackFrame;
  TStackFrame = record
    CallersEBP: DWORD;
    CallerAdr: DWORD;
  end;

{$STACKFRAMES OFF}

function GetEBP: Pointer;
asm
        MOV     EAX, EBP
end;

function GetStackTop: DWORD;
asm
        MOV     EAX, FS:[4]
end;

{$STACKFRAMES ON}

function Caller(Level: Integer): Pointer;
var
  TopOfStack: Cardinal;
  BaseOfStack: Cardinal;
  StackFrame: PStackFrame;
begin
  Result := nil;
  try
    StackFrame := GetEBP;
    BaseOfStack := Cardinal(StackFrame) - 1;
    TopOfStack := GetStackTop;
    while (BaseOfStack < Cardinal(StackFrame)) and (Cardinal(StackFrame) < TopOfStack) do
    begin
      if Level = 0 then
      begin
        Result := Pointer(StackFrame^.CallerAdr - 1);
        Break;
      end;
      StackFrame := PStackFrame(StackFrame^.CallersEBP);
      Dec(Level);
    end;
  except
    Result := nil;
  end;
end;



--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
LamerTM
Дата 16.5.2009, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



О! Спасибо огромное. Как раз то что нужно.
Правда оказалось что теперь везде надо понаставить published, ну да ладно. Все равно я в силу своего ламерства не знаю какие это имеет издержки  smile и имеет ли.
Спасибо еще раз.
PM MAIL   Вверх
CodeMonkey
Дата 16.5.2009, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



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


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0534 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.