メソッド トレース用の次の典型的なコードを考えてみましょう (説明のために簡略化しています)。
type
IMethodTracer = interface
end;
TMethodTracer = class(TInterfacedObject, IMethodTracer)
private
FName: String;
FResultAddr: Pointer;
FResultType: PTypeInfo;
public
constructor Create(
const AName: String;
const AResultAddr: Pointer = nil;
const AResultType: PTypeInfo = nil);
destructor Destroy; override;
end;
constructor TMethodTracer.Create(
const AName: String;
const AResultAddr: Pointer;
const AResultType: PTypeInfo);
begin
inherited Create();
FName := AName;
FResultAddr := AResultAddr;
FResultType := AResultType;
Writeln('Entering ' + FName);
end;
destructor TMethodTracer.Destroy;
var
lSuffix: String;
lResVal: TValue;
begin
lSuffix := '';
if FResultAddr <> nil then
begin
//there's probably a more straight-forward to doing this, without involving TValue:
TValue.Make(FResultAddr, FResultType, lResVal);
lSuffix := ' - Result = ' + lResVal.AsString;
end;
Writeln('Leaving ' + FName + lSuffix);
inherited Destroy;
end;
function TraceMethod(
const AName: String;
const AResultAddr: Pointer;
const AResultType: PTypeInfo): IMethodTracer;
begin
Result := TMethodTracer.Create(AName, AResultAddr, AResultType);
end;
//////
function F1: String;
begin
TraceMethod('F1', @Result, TypeInfo(String));
Writeln('Doing some stuff...');
Result := 'Booyah!';
end;
F1();
これは意図したとおりに機能しています。出力は次のとおりです。
F1に入る
何かをしている...
F1を去る - 結果= Booyah!
への呼び出しに必要なパラメーターの数を最小限に抑える方法を探しています。理想的には、-関連の引数を完全TraceMethod()
にスキップできるようにします。Result
私はアセンブラやスタックレイアウトの経験はありませんが、間違っていなければ、他の人が見た「魔法」から判断すると、少なくとも暗黙の魔法のメモリアドレスResult
-変数は何らかの方法で取得できるはずです。 ? そして、そこから型情報を取得することもできますか?
もちろん、引数をTraceMethod
完全に渡す必要がなくなる「周囲の」関数自体の名前を特定することさえできれば...
Delphi XE2 を使用しているため、最近導入されたすべての言語/フレームワーク機能を使用できます。
そして、誰かが言及する前に: 私の実際のコードは既に-callsの代わりにCodeSite.EnterMethod
/を使用しています。また、この単純化された例は複雑な型を処理できず、エラー処理をまったく実行しないことも認識しています。ExitMethod
Writeln