ik | 18 Jun 2012 23:22
Picon
Gravatar

Dynamically Execute method

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
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@...
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Bernd | 18 Jun 2012 23:51
Gravatar

Re: Dynamically Execute method

2012/6/18 ik <idokan@...>:
> 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.
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@...
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

ik | 19 Jun 2012 00:49
Picon
Gravatar

Re: Dynamically Execute method

On Tue, Jun 19, 2012 at 12:51 AM, Bernd <prof7bit <at> googlemail.com> wrote:
2012/6/18 ik <idokan-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> 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  -  fpc-pascal-PD4FTy7X32k2wBtHl531yWD2FQJk+8+b@public.gmane.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@...
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Ludo Brands | 19 Jun 2012 09:28
Picon
Favicon

RE : Dynamically Execute method


> 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

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

Ludo Brands | 19 Jun 2012 09:38
Picon
Favicon

RE : RE : Dynamically Execute method


> 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

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

ik | 19 Jun 2012 12:38
Picon
Gravatar

Re: RE : RE : Dynamically Execute method

On Tue, Jun 19, 2012 at 10:38 AM, Ludo Brands <ludo.brands-GANU6spQydw@public.gmane.org> wrote:

> 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 :)
 


Ido
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@...
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Mattias Gaertner | 19 Jun 2012 09:37
Picon
Favicon

Re: Dynamically Execute method

On Tue, 19 Jun 2012 00:22:29 +0300
ik <idokan@...> wrote:

> 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
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@...
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Gmane