Форум: "Основная";
Текущий архив: 2003.09.22;
Скачать: [xml.tar.bz2];
ВнизВозможно ли в теле метода узнать его имя ? Найти похожие ветки
← →
Unknown (2003-09-10 11:29) [0]Если да то как ?
← →
PVOzerski (2003-09-10 11:32) [1]Общего решения не вижу. Но если не секрет, в какой ситуации это может понадобиться?
← →
Digitman (2003-09-10 11:36) [2]смотря какой метод
если это published-метод, то инф-ция о его имени хранится в RTTI, и получить эту инф-цию можно вызвав метод MethodName() с указанием адреса точки входа в тек.исп.метод
← →
Unknown (2003-09-10 11:39) [3]PVOzerski © (10.09.03 11:32):
Нужно логировать вызов методов КОМ обекта и хочется написать общую процедуру. Придется руками :(.
← →
Unknown (2003-09-10 11:40) [4]Digitman © (10.09.03 11:36)
понял, спасибо за ответ.
← →
Digitman (2003-09-10 11:46) [5]
> Unknown
если объект реализует диспинтерфейс, достаточно переопределить метод Invoke() и в теле его первым делом идентифицировать параметр DispID
case DispID of
1: Log("Method1");
2: Log("Method2");
...
end;
← →
Verg (2003-09-10 11:59) [6]Мне кажется, что эта задача бессмысленна.
Мм.. получится что-то типа задать вопрос:
"Эй, Сидоров, у тебя какая фамилия?"
← →
PVOzerski (2003-09-10 12:08) [7]Вот и я о том же. Обычно важнее узнать имя класса, потому что наследуемые переопределяемые методы либо автоматически (virtual/override), либо потому что так принято (dynamic/override, message) имеют одни и те же имена. А какая может быть другая ситуация? Вызывать метод "от балды": нашел в классе, обрадовался - а дай-ка вызову? :^)
← →
Unknown (2003-09-10 12:18) [8]PVOzerski © (10.09.03 12:08)
я же сказал что во всех методах нужно вызвать процедуру для логирования например:
procedure TMyObject.AddLog(AFlag: Integer; AMethod: string;
AParams: array of string);
begin
...
end;
function TMyObject.MySomeMethod(AParam1, AParam2: string);
begin
...
AddLog(Result, "MySomeMethod", [AParam1, AParam2]);
...
end;
Вот имя метода тут хотел и узнать ф не писать руками.
Ато может показатся бесмысленным но если методов очень много то работы прибавляется ...
← →
Nikolay M. (2003-09-10 12:20) [9]Теоретически - может быть через VMT? Получить в AddLog адрес возврата из стека, найти в VMT, какой функции соответствует этот адрес.
← →
PVOzerski (2003-09-10 12:23) [10]Пожалуй, с точки зрения набираемого вручную кода выискивать каждый раз имя метода через RTTI выигрыша не даст. Вам же все равно придется явно указывать строкой имя, которое надо искать. Self ведь тут не поможет.
← →
Unknown (2003-09-10 12:28) [11]PVOzerski © (10.09.03 12:23)
Я уже понял что не получится.
Всем спасибо!
Пока.
← →
PVOzerski (2003-09-10 12:28) [12]2Nikolay M: если учесть, что число передаваемых через стек параметров может быть различным, это потребует не самого тривиального кода. Хотя, пожалуй, его ведь можно получить из high от открытого массива параметров, все равно в AddLog передаваемого. Пожалуй, этот путь может пройти - если, конечно, метод в VMT присутствует. А если он не виртуальный?
← →
Nikolay M. (2003-09-10 12:33) [13]
> PVOzerski © (10.09.03 12:28) [12]
Как это передаваемое кол-во различно?
> procedure TMyObject.AddLog(AFlag: Integer; AMethod: string;
> AParams: array of string);
Вроде бы тут 3 фиксированных параметра, если я правильно считаю array of string за указатель.
Впрочем, я и говорю: теоретически...
Имхо, овчинка выделки не стОит...
← →
PVOzerski (2003-09-10 12:46) [14]>Вроде бы тут 3 фиксированных параметра, если я правильно считаю array of string за указатель.
Э нет, Addlog-то не тот метод, имя которого надо получить. Надо получить имя метода, из которого AddLog вызван, как я понял. А AddLog - он-то всегда "AddLog".
>Имхо, овчинка выделки не стОит...
Согласен, хотя, пожалуй, задача принимает занятные очертания. Правда, играться лень.
← →
Verg (2003-09-10 12:49) [15]В VMT хранится указатель на таблицу только published методов.
В самой VMT хранятся адреса виртуальных методов.
Адреса виртуальных методов - это всего лишь адреса, имен нет.
итак, зная адрес метода можно получить его имя только для published, будь он виртуальным или не.
Как узнать адрес метода?
Вопрос можно трансформировать так - как в процедуре узнать точку входа в нее, не называя ее имени в тексте этого участка кода самой процедуры?
← →
MBo (2003-09-10 12:54) [16]>как в процедуре узнать точку входа в нее
что-то типа
procedure TForm1.Button1Click(Sender: TObject);
var p:pbyte;
function DummyFunc: Pointer;
asm
xor eax, eax
end;
begin
p:=@DummyFunc;
inc(p,4);
label1.caption:=classname+"."+methodname(p);
end;
← →
PVOzerski (2003-09-10 12:55) [17]>Вопрос можно трансформировать так - как в процедуре узнать точку
>входа в нее, не называя ее имени в тексте этого участка кода
>самой процедуры?
Так вроде Nikolay M. указал путь: порыться по стеку, пока мы из метода не вывалились.
← →
Nikolay M. (2003-09-10 12:56) [18]
> Надо получить имя метода, из которого AddLog вызван, как
> я понял.
Ну да. Но в стеке-то лежат параметры именно AddLog-а + точка возврата. А у AddLog-а всего 3 параметра.
← →
PVOzerski (2003-09-10 13:03) [19]2MBo: А точно ли точка входа в заглушку совпадет с точкой входа в метод? IMHO, этого быть не может, иначе бы при вызове метода управление передавалось бы сразу же на заглушку (т.е. неправильно) или каждая процедура, имеющая вложенные, начиналась бы с JUMP"а к собственно телу. Я сомневаюсь, что оптимизатор у Delphi такой дурной (вернее, уверен, что это не так).
2 Nikolay M.: а есле в стеке дальше порыться. Мы ведь не вышли не только из AddLog, но и из метода, который этот AddLog вызвал. Впрочем, в стеке ведь мы найдем точку возврата, а не начальную точку входа...
← →
Nikolay M. (2003-09-10 13:12) [20]
> Мы ведь не вышли не только из AddLog, но и из метода, который
> этот AddLog вызвал.
Да, вот тут действительно возникнет любой вызывающий метод с любым числом параметров...
← →
PVOzerski (2003-09-10 13:19) [21]> с любым числом параметров...
А это-то число в AddLog передается "полуавтоматически" - получаемо в теле AddLog как High от открытого массива-параметра + 1. Если, конечно, логить все параметры.
← →
Verg (2003-09-10 13:25) [22]
> PVOzerski © (10.09.03 13:03) [19]
MBo прав.
Адрес метода будет равен адресу последней лок процедуре+4 (+4 - это просто выравнивание на границу слова, на самом деле заглушка занимает 1 байт (ret).
procedure TMyObject.SomeMethod;
var P : pointer;
procedure Dummy;
begin
end;
begin
P:=Pchar(@Dummy)+4;// Вот, собственно, p содержит адрес SomeMethod
....
end;
← →
Кто-то (2003-09-10 13:26) [23]Если речь идет о логе, то все просто. В самих методах лог не пишем, а вместо этого вызываем Assert. В Application.OnException получаем строку E.Message, из которой извлекаем имя метода, а потом вызываем запись в лог. Параметры записи (если они нужны) можно передавать из метода через глобальную строковую переменную, либо через динамический массив строк (инициализируем перед вызовом Assert).
← →
Nikolay M. (2003-09-10 13:29) [24]Да, стопудово затраченные усилия себя не оправдают...
Если только в целях повышения образованности :)
← →
Verg (2003-09-10 13:33) [25]
> из которой извлекаем имя метода, а потом вызываем запись
> в лог.
Да? А где там имя метода?
← →
PVOzerski (2003-09-10 13:34) [26]2Verg © (10.09.03 13:25) [22]
Вы правы :^) Хотя путь-то все равно ненадежный: мало ли какой код вздумает вставить в заглушку тот или иной компилятор и мало ли в каком порядке разместит код функций.
← →
Verg (2003-09-10 13:38) [27]
> PVOzerski © (10.09.03 13:34) [26]
Да, все это верно. Конечно, такой метод - это не стопроцентное решение, мало того, еще и некорректное, т.к. исходит из особенностей конкретной версии конкретного компилятора. В какой-нибудь Delphi 9 компиллер будет размещать код локальных процедур после кода основной - и все, "полный досвидан"... :)
← →
Verg (2003-09-10 13:40) [28]Но главное ---
Если напрячься (:))), то какое-нибудь решение (пусть локально), но найти можно...
← →
Кто-то (2003-09-10 13:44) [29]> Verg © (10.09.03 13:33) [25]
Да, действительно, спутал. Имени метода там нет.
Зато там есть есть имя модуля и номер строки в нем. Если речь идет о логе ошибок или чем-то подобном, то разработчику как раз эта информация и нужна.
← →
Vuk (2003-09-10 14:03) [30]Насколько помню, замечательная фича есть на этот счет в ModelMaker. Если не ошибаюсь, там для любого метода можно установить флажок "Instrumented", и тогда автоматически в начало или конец метода будет вставлен определенный код. Этот код генерируется по задаваемым пользователем шаблонам, синтаксис которых обеспечивают подстановку имени метода в нужное место.
← →
Erik (2003-09-10 14:50) [31]Насколько я понял есть полное решение лоя данной задачи. Если такой класс TJclExceptFrame он возвращает описание всех методов в стеке. Вобщето это обрабочик ошибок, но можно его приспособить для создания лога и что важно непридется много возится.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.09.22;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.013 c