Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2012-06

Dynamically Execute method

7 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

ik

Hi,

I'm playing a bit with the notion of execute a method dynamically on demand. I'ved created the following PoC:
https://gist.github.com/2950789

It works, but for some strange reason, I find myself feeling that I'm missing something, or it should be done differently. Does this code written properly, or should I do it differently ?

Thanks,
Ido

Reply by email

Bernd
to ik

2012/6/18 ik :

Show quoted text 5 lines
Hi, I'm playing a bit with the notion of execute a method dynamically on demand. I'ved created the following PoC: https://gist.github.com/2950789

Souldn't this be

Exec: procedure of object;

instead of only procedure? Imho one pointer alone can not be enough, it should need the address of the procedure *and* the address of the object instance. Does your example work with multiple instances of the same class? If yes then I really don't understand why. But I also did not test it myself.

Reply by email

ik
to Bernd
Bernd wrote 18 lines
2012/6/18 ik : > Hi, > > I'm playing a bit with the notion of execute a method dynamically on demand. > I'ved created the following PoC: > https://gist.github.com/2950789 Souldn't this be Exec: procedure of object; instead of only procedure? Imho one pointer alone can not be enough, it should need the address of the procedure *and* the address of the object instance. Does your example work with multiple instances of the same class? If yes then I really don't understand why. But I also did not test it myself.

Seems to work for me, updated the example: https://gist.github.com/2950789

Or am O missing something ?

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Ludo Brands
to ik
Seems to work for me, updated the example: https://gist.github.com/2950789 Or am O missing something ?

Change your method to

procedure TMyClass.SayHi;
begin
  writeln('Hi World from '+IntToStr(ptruint(self)));
end;

And the test to

 write('From MyClass2 : ');
 MyClass2.SayHi;
 if not ExecMethod(MyClass2, 'SayHi') then
   writeln(STDERR, 'Could not find SayHi method on MyClass2 instance');

And you'll get something like:

From MyClass : Hi World from 482800

Hi World from 4199728

From MyClass2 : Hi World from 482816

Hi World from 4199728

As Bern said you can't call an object method without passing the reference to the instance. In this case you are lucky because TMyClass.SayHi doesn't use any properties or class vars. Add a property to TMyClass and try to writeln that property and you will see it fails. What you are doing here is calling SayHi as if it where a class method.

Ludo

Reply by email

Mattias Gaertner
to ik: I'm playing a bit with the notion of execute a method dynamically on demand. I'ved…
Show quoted text 9 lines
Hi, I'm playing a bit with the notion of execute a method dynamically on demand. I'ved created the following PoC: https://gist.github.com/2950789 It works, but for some strange reason, I find myself feeling that I'm missing something, or it should be done differently. Does this code written properly, or should I do it differently ?
function ExecMethod(Instance : TObject; Name : String) : Boolean;
var Exec : TMethod;
begin
  Exec.Code := TProcedure(Instance.MethodAddress(Name));
  Exec.Data := Instance;
  Result := Assigned(Exec.Code);
  if Result then TProcedureOfObject(Exec)();
end;

Mattias

Reply by email

Ludo Brands
to Ludo Brands: Change your method to procedure TMyClass.SayHi; begin writeln('Hi World from…
Show quoted text 7 lines
As Bern said you can't call an object method without passing the reference to the instance. In this case you are lucky because TMyClass.SayHi doesn't use any properties or class vars. Add a property to TMyClass and try to writeln that property and you will see it fails. What you are doing here is calling SayHi as if it where a class method.

Here is the correct way of doing it:

function ExecMethod(Instance : TObject; Name : String) : Boolean;
type
  TProc= procedure of object;
var
  method : TMethod;
  exec:tproc;
begin
  method.Data := Pointer(Instance);
  method.Code := Instance.MethodAddress(Name);
  Exec:=TProc(Method);
  Result := Assigned(method.Code);
  if Result then Exec;
end;

Output:

From MyClass : Hi World from 482800

Hi World from 482800

From MyClass2 : Hi World from 482816

Hi World from 482816

Ludo

Reply by email

ik
to Ludo Brands
Ludo Brands wrote 34 lines
> As Bern said you can't call an object method without passing > the reference to the instance. In this case you are lucky > because TMyClass.SayHi doesn't use any properties or class > vars. Add a property to TMyClass and try to writeln that > property and you will see it fails. What you are doing here > is calling SayHi as if it where a class method. > Here is the correct way of doing it: function ExecMethod(Instance : TObject; Name : String) : Boolean; type TProc= procedure of object; var method : TMethod; exec:tproc; begin method.Data := Pointer(Instance); method.Code := Instance.MethodAddress(Name); Exec:=TProc(Method); Result := Assigned(method.Code); if Result then Exec; end; Output: >From MyClass : Hi World from 482800 Hi World from 482800 >From MyClass2 : Hi World from 482816 Hi World from 482816 Ludo

Thank you Ludo, Mattias and Bernd.
It works well now :)

Show quoted text 5 lines
_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Ido

Reply by email