我正在建立一个日志系统,所以我使用JclDebug单元使用ProcByLevel
函数获取当前调用程序或函数的名称之类的堆栈信息。但现在我想获得调用者TObject的地址(Pointer)(适用时)。
我想编写一个函数,它传递调用方法的指针可以返回一个包含这种方法的TObject的实例。像这样
function GetCallerObject(CallerMethodAddress: Pointer) : TObject;
begin
//here I'm lost
end;
请参阅此代码
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
JCLDebug,
SysUtils;
Type
TFooClass=class
public
procedure methodCaller;
end;
procedure Show;
var
s : string;
i : Integer;
LocationInfo : TJclLocationInfo;
begin
Writeln('show');
//values for the levels are harcoded for this sample
LocationInfo:=GetLocationInfo(Caller(1));
Writeln(ProcByLevel(1)+' '+Format('Caller %s %p',[LocationInfo.ProcedureName, LocationInfo.Address ]));
//here I want get the address of TFooClass class which calls this method (Show)
Writeln(GetCallerObject(LocationInfo.Address).ClassName); //this must return TFooClass
end;
procedure TFooClass.MethodCaller;
begin
Writeln(Format('Self %p',[Pointer(Self)]));
Writeln(Format('Real Caller Address %p',[Caller(0)]));
show;
end;
var
M : TFooClass;
begin
try
M:=TFooClass.Create;
try
M.methodCaller;
finally
M.Free;
end;
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
使用上面的代码我得到了一些地址,但没有一个与调用者对象的地址(TFooClass的Self)匹配,我真的读了JclDebug单元的完整代码,但我没有找到任何引用调用者对象,只能检索包含我正在寻找的类名的堆栈名称,这样才能认为哪些必须可以返回调用者TObject的地址,但是现在我是' m真的输了。
那么,我如何从使用JclDebug的方法中获取调用者TObject的地址?
答案 0 :(得分:3)
通常,由于以下原因,此信息不可用:
Self
。Self
引用。请注意,Self
只是一个参数,通常在eax
或rax
中传递。并且在代码运行时,该寄存器的内容可能已经改变。