3
votes

How can i determine who called the Showme Procedure?

procedure Showme(str:string);
begin
  ShowMessage(str);
end;

procedure btnclick(sender:TObject);
begin
  Showme("test");
end;

procedure btn2click(sender:TObject);
begin
  Showme("test");
end;

Edit : The Confusion

Showme(654, '654'); // procedure name, string
Showme(654, '564');
4
What are you using to generate "The Confusion". The code you've posted won't generate that output. If your two click events say Showme("654") and Showme("564") then that would make sense (but makes your question meaningless). - Мסž
The Confused Procedure is my suggestion to my friend. But he won't use it. - Orhan Cinar
I understand the original question better than the edited version (but that's me probably), but I don't understand the downvotes?! - Lieven Keersmaekers
I fail to understand what you mean with your edit. If Showme is a procedure that requires exactly one argument, of course it will not compile if you pass two arguments to it. - Andreas Rejbrand
Upvote this. Downvoting without giving a reason is a bad habit. - mjn

4 Answers

9
votes

There's no built-in way for one procedure to know which procedure called it. You can use stack tracing if you really need to know, but that sort of data is really only needed for debugging. For actual execution, what matters is the data that's passed to the routines, not where it came from. That's one of the basic principles of structured programming. If two different routines call the same procedure with the same data, it should treat them both the same.

What exactly are you doing where you need to be able to tell the difference? There might be a simpler way to accomplish it.

8
votes

Why don't you pass a different constant or even the name of the procedure calling it as a parameter of Showme? It is possible to analyze the stack in order to determine the name of the calling function but it is much more complicated and you need to add information about linking (map file). Jedi's JCL has some functions that can help you but I would use an additional parameter.

2
votes

I will assume you're running the application in the debugger, so you can put a breakpoint inside the Showme procedure and when the program stops, activate the stack view (view/debug windows/Call stack).

It will show you who called it and actually if you double click on any stack entry the IDE will walk you to the exact line of code that makes the call (in case showme is called more than once per calling routine).

BTW: I think you have to make a better effort to express your question.

2
votes

TVirtualMethodInterceptor allows to execute code before and after the actual method, and there is a Method parameter which contain the method name:

Example code:

type
  TFoo = class
  public
    procedure Bar; virtual;
  end;

procedure InterceptorBefore(Instance: TObject; Method: TRttiMethod;
  const Args: TArray<TValue>; out DoInvoke: Boolean; out Result: TValue);
begin
  ShowMessage('Before: ' + Instance.ClassName + '.' + Method.Name);
end;

procedure InterceptorAfter(Instance: TObject; Method: TRttiMethod;
  const Args: TArray<TValue>; var Result: TValue);
begin
  ShowMessage('After: ' + Instance.ClassName + '.' + Method.Name);
end;

{ TFoo }

procedure TFoo.Bar;
begin
  ShowMessage('TFoo.Bar');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  interceptor: TVirtualMethodInterceptor;
  foo: TFoo;
begin
  foo := TFoo.Create;

  interceptor := TVirtualMethodInterceptor.Create(TFoo);
  interceptor.Proxify(foo);
  interceptor.OnBefore := InterceptorBefore;
  interceptor.OnAfter := InterceptorAfter;

  foo.Bar;

end; 

Note this is new in Delphi XE so I can not test and verify it on my system.