A r t i c l e s
Navigation

Note: This Wiki is
outdated, personal views
may have changed.
L505 A.I. bot is dead
long live THX 1138

M a i n P a g e

D i r e c t o r y

Procedure vs Procedure Of Object Hack


See also Procedure Bound To Method Without RTTI Hack
Ever want to use a regular procedure when a procedure is required to be 'of object'?

I'm not sure if this is safe to do, but using some tricks we can turn a regular procedure type into being compatible with a procedure method inside a class, i.e a procedure of object bound to a plain procedure.

Note the {$M+} switch is used to turn on 'type information', otherwise the program below won't execute the Tx.P() method.

program test; {$mode objfpc} {$H+}{$M+}

type 
  Tx = class
  //  published
    procedure p;
  end;

procedure Tx.p;
begin
  writeln('proc test');
end;

var 
  x: Tx;
  p: procedure;  // normally we would need procedure OF OBJECT

begin
  x:= Tx.create;
  pointer(p):= x.MethodAddress('p');
  if assigned(p) then 
    p()  // call a regular procedure and not 'of object'? Magic.
  else 
    writeln('unassigned');
  x.free;
  readln;
end.

And now for the real trickery:
program test29; {$mode objfpc} {$H+}{$M+}

type 
  Tx = class
    procedure p;
    procedure test(i: integer);
  private
    s: string;
  end;

procedure Tx.p;
begin
  writeln('proc test 1');
  // how does this method know about SELF? take a guess
  self.s:= 'hello ';
  self.s:= 'hello ' + s + s;
  writeln(self.s);
end;


procedure Tx.test(i: integer);
begin
  writeln('proc test 2');
  // how does this method know about SELF? take a guess
  self.s:= 'hello ';  
  self.s:= 'hello ' + s + s + ' see number: ';
  writeln(self.s, i);
end;

var 
  x: Tx;
  // normally we would need procedure OF OBJECT
  p: procedure(fakeself: pointer);  
  // the pointer acts as our object SELF
  test: procedure(fakeself: pointer; i: integer);  

  // alternatively: don't have to use a pointer.. we can use Tx
  // test: procedure(fakeself: Tx; i: integer);  


begin
  x:= Tx.create;
  // bind regular procedures to an object method
  pointer(p):= x.MethodAddress('p');
  pointer(test):= x.MethodAddress('test');
  if assigned(p) then 
  begin
    // now launch the procedures
    p(pointer(x));           
    test(pointer(x), 600);  { pointer is our hidden SELF param }
  end else 
    writeln('unassigned');
  x.free;
  readln;
end.

Points/theories to think about and question:
  • a regular procedure can be faked/binded to an object method
  • regular procedures have benefits, such as exportable from DLL, or simplicity when an object/class is not needed.
  • how to obtain object instance if we were playing with DLL? Get it/export it using something like GetObjInstance()
  • VMT/RTTI (as and is) issues.. think about problems there


About
Note: This Wiki is outdated, personal views may have changed.

This wiki contains info on life, health, humans, nature, programming, database, fads, paradigms, poems, principles, theories.

Articles may contain statements which some may find helpful and encouraging, or even discouraging.

Beware, I believe in the Grand Justice system.
_ _ _