#1 2010-12-17 16:10:14

Zorglub
Member
Registered: 2010-12-17
Posts: 3

Ptr to call local function

est ce que tu connais cette technique pour appeler une fonction locale par l'intermediaire d'un pointeur  ?


function MagicCaseOf(ABasePointer:Pointer; const AIndex:Integer; const AProcTab:array of TProcedure):Integer;overload;
begin
  if (AIndex >= Low(AProcTab)) and (AIndex <= High(AProcTab)) then
  begin
    Result := AIndex;
    asm push ABasePointer end;
    AProcTab[Result]();
    asm pop ABasePointer end;
  end
  else Result := -1;
end;

function MagicCaseOf(const AIndex:Integer; const AProcTab:array of TProcedure):Integer;
var
  BasePointer: Pointer;
begin
  asm push [ebp] end;       // BasePointer
  asm pop BasePointer end;

  Result := MagicCaseOf(BasePointer, AIndex, AProcTab);
end;


procedure TMainForm.Button1Click(Sender: TObject);
var
  Val0, Val1:Integer;
  value:Integer;
  procedure ExecProc0();
  begin
    ShowMessage('ExecProc0 ' + IntToStr(Val0));
  end;
  procedure ExecProc1();
  begin
    ShowMessage('ExecProc1 ' + IntToStr(Val1));
  end;
begin
  Val0 := 111;
  Val1 := 222;
  value := 1;
  if MagicCaseOf(value , [@ExecProc0,@ExecProc1]) = -1 then
    ShowMessage('else');
end;

Offline

#2 2010-12-17 16:29:14

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,206
Website

Re: Ptr to call local function

Sounds a bit complicated to me.
Restore the stack based pointer, needed for local procedures, works.
But why use this?

A more suitable solution could be to use anonymous methods, and a newer Delphi version.
Or use another code architecture. If the called procedures are local, I don't get the point here. You've them declared, so a

case Value of
  0: ExeProc0;
  1: ExeProc1;
  else ShowMessage('else');
end;

will do the same, with less obfuscation.

Offline

#3 2010-12-17 16:43:18

Zorglub
Member
Registered: 2010-12-17
Posts: 3

Re: Ptr to call local function

c'était juste un exemple !

je l'utilise dans une HashTable quand je parcours toute la table:

procedure Essai;
  procedure Proc1(AItem:TItem);
  begin
     /////traitement pour chaque item
  end;
begin
  HashTable.TraverseLocal(@Proc1);
end;

c'est très pratique!

Offline

#4 2010-12-17 17:15:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,206
Website

Re: Ptr to call local function

What I've done in such situation is to use an "opaque" structure or a record.

For example:

type
  TParams: record
    one: integer;
    two: string;
  end;

  procedure Process(var opaque);
  var Params: TParams absolute opaque;
  begin
     writeln(Params.One);
  end;

procedure Local;
var Params: TParams;
begin
  Params.One := ..
  HashTable.TraverseLocal(@Process,Params);
end;

This is still valid Delphi code, will work on any version of compiler/CPU, and is easy to use.
In fact, the TParams structure is your local stack variables you pass explicitely via a var parameter. No push/pop asm trick needed.

Offline

Board footer

Powered by FluxBB