Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Multi-Event-Liste (https://www.delphipraxis.net/191050-multi-event-liste.html)

Ghostwalker 2. Dez 2016 12:17

Multi-Event-Liste
 
Hi,

ich bin gerade drüber mir eine "Multi-Event-Liste" zu bauen, die verschiedene Event-Typen mehrfach
speichert und ggf. auch ausführt.


Delphi-Quellcode:
TYPE
  PEventEntry = ^TEventEntry;
  TEventEntry = record
                  method : TMethod;
                  ident : widestring;
  end;

  TIndexArray = array of Integer;


  TEventList = Class(TObject)
    private
       flist : TList;
    protected
       procedure Clear;

       function indexOf(value:TMethod;ident:widestring):integer;

    public
       Constructor Create;
       Destructor Destroy;override;

       Procedure Add(value:TMethod;ident:widestring);
       procedure Del(value:TMethod;ident:widestring);

       function getIdentCount(ident:widestring):integer;
       function getIdentIndexs(ident:widestring):TIndexArray;
       function getMethodByIdent(idx:integer;ident:widestring):TMethod;

    published
  End;
Nun würd ich gerne das ansprechen (Auslösen quasi) der einzelnen Eventhandler-Typen ebenfalls in die Liste verlagern (abfolge is ja immer gleich, nur die Parameter sind unterschiedlich).

Und genau da häng ich im Moment.

Ich würde das ganze gerne in form: eventlist.execute('TMyEventType',[param1,param2]) aufrufen.

TMethod als solches kennt aber keine Parameter, und den Typ des Events hab ich (im Moment) nur als String, so das ich hier auch nicht casten kann.

Hat jemand einen Lösungsansatz oder sowas für das Problem ?

Jens01 2. Dez 2016 13:41

AW: Multi-Event-Liste
 
Bei dem Spring4D-Projekt gibt es so ein Ding.

Ghostwalker 2. Dez 2016 17:42

AW: Multi-Event-Liste
 
Jep...und auch in DSharp. Beides ist für mich aber nicht wirklich brauchbar. Mein Delphi (und der Rechner) sind dafür schon ein bischen alt :)


Bei der Suche nach einer Lösung bin ich auf diesen Beitrag gestoßen:

http://www.delphipraxis.net/171641-a...orrekt-so.html

Problem ist der Parametertyp PParameters. Den kennt mein Delphi nicht, also hab ich das
mal einfach als Pointer definiert.

Damit kann ich eine Methode ohne Parameter (bzw. nur mit self als Parameter) aufrufen. Andere
Parameter mag er so aber nicht.

Kann mir da jemand sagen wie PParameter in neueren Delphis definiert ist ?

Ghostwalker 4. Dez 2016 23:07

AW: Multi-Event-Liste
 
So..hab ein wenig weiter probiert. Folgende Methode ist dabei soweit rausgekommen:

(Gekürzt...Problem ist der ASM-Teil):

Delphi-Quellcode:
procedure TEventList.CallInvoke(method: TMethod; params: array of const);
var
  :
  Regs     : array[plEAX..plECX] of Cardinal;
  doStack  : boolean;
  stack    : array[0..1023] of Byte;
  stacksize : integer;
  sc       : integer;
  p        : Pointer;


begin
  Regs[plEAX] := Cardinal(Method.data);
  if (doStack) then
  begin
    fillchar(stack,sizeof(stack),0);
    StackSize := Sizeof(TVarRec)*(Length(Params));
    sc := 0;
    for I := High(params) downto Low(Params) do
    begin
      move(params[i],stack[sc],sizeof(params[i]));
      inc(sc,sizeof(params[i]));
    end;
    p := @Stack;
    asm
            SUB    ESP,Stacksize
            MOV    p,ESP
    end;
    Regs[plEDX] := Cardinal(p);
    Regs[plECX] := Cardinal(Stacksize);
  end
  else
  begin
    for I := 0 to MethSig.ParamCount - 1 do
    begin
      if (MethSig.parameters[i].location <> plEax) AND (MethSig.parameters[i].ParamName <> 'Self') then
         Regs[MethSig.Parameters[i].Location] := GetValueAsCardinal(params[i-1]);
    end;
  end;
  // Do the call
  asm
            MOV    EAX,DWORD PTR Regs[0]
            MOV    EDX,DWORD PTR Regs[4]
            MOV    ECX,DWORD PTR Regs[8]
            CALL   Method.code
            MOV    DWORD PTR Regs[0],EAX
            MOV    DWORD PTR Regs[4],EDX
  end;
End;
Zum Testen verwendig ich folgenden Aufruf:

Delphi-Quellcode:
var
  rec : TTestRec;

begin
  rec.aInteger := 55779;
  rec.aString := 'More wide string to process';
  rec.aBool := TRUE;
  fevents.Execute('TEventType5',[150,333,42,'Schweine im Weltraum oder Trampen leicht gemacht',FALSE,1.5647,'Normal String','Another very wide String',@rec,2357]);
end;
TEventType5 ist so definiert:

Delphi-Quellcode:
   TEventType5 = Procedure(v1:integer;v2:integer;v3:integer;v4:Widestring;v5:boolean;v6:double;v7:string;v8:widestring;v9:TTestRec;v10:integer) of object;
Soweit so gut. Leider Schepperts beim Aufruf der obigen Methode mit diesem EvenType. Benutze ich
einen mit nur 2 oder 1 Parameter (egal was für ein Typ) funktioniert das ganze. Also hakt es mit
dem Stack-Teil. Könnte mir da jemand bitte helfen ?

Stevie 5. Dez 2016 12:14

AW: Multi-Event-Liste
 
Hol dir Delphi 10 Berlin Starter für lau und nimm Spring4D :mrgreen:

Zu deinem Problem:
du kannst nicht einfach alle Parametertypen gleich behandeln. Siehe http://www.guidogybels.eu/asmtable3.html

Ghostwalker 5. Dez 2016 12:46

AW: Multi-Event-Liste
 
Jup...weiß ich. Bin inzwischen ein wenig weiter gekommen.

Statt der Methode aus der ObjAuto, verwend ich deine Routine aus DSharp.

Dabei bau ich den PParameters selbst zusammen, anhand der Typen.

Delphi-Quellcode:
  //Fillup PParameters for calling the method and handling the stack
  //and calculating the Stacksize
  New(para);
  fillchar(para^,sizeof(para^),0);
  StackSize := 0;
  sc := 0;
  for i := MethSig.paramCount-1 downto 1 do
  begin
    case MethSig.Parameters[i].Location of
       plEDX : para^.Registers[plEDX] := GetValueAsCardinal(params[i-1]);
       plECX : Para^.Registers[plECX] := GetValueAsCardinal(params[i-1]);
    ELSE
      if(MethSig.Parameters[i].Location > plECX) then
      begin
        v := @params[i-1];
        MoveValue(v,para,stacksize);
      end;
    end;
  end;
  InvokeMethod(Method,para,stacksize);
  dispose(para);
Aufruf:

Delphi-Quellcode:
fevents.Execute('TEventType6',[150,333,42,true,'Wuptidupti']);
Das Problem ist der 3 Parameter im Array (also die 42), die wird einfach mit 0 übergeben. Der Rest passt.

Ghostwalker 5. Dez 2016 13:18

AW: Multi-Event-Liste
 
Jut...auch das Problem ist gelöst. Lag an der Stackgröße die bei Boolean und Char falsch berechnet wurde.....dafür ist nu ein neues aufgetreten.

Nämlich wenn ich mehrere Widestrings übergeben will....mal guggen.

Ghostwalker 5. Dez 2016 13:32

AW: Multi-Event-Liste
 
Auch erledigt. Bei Stringkonstanten (execute(...,['wupti']); wird automatisch ein AnsiString draus gemacht. Wenn die ZielMethode natürlich Widestring erwartet ist das nicht gut.

Ghostwalker 5. Dez 2016 14:03

AW: Multi-Event-Liste
 
Geschaft.....MultiEvent-Liste funktioniert soweit (siehe Testprojekt im Anhang).

Tests, Anregungen usw. sind natürlich immer willkommen :)

Auf meiner TODO-Liste dafür:


- Records als Parameter
- autom. Type-Konvertierung (versch. String-Typen z.B.)

DeddyH 5. Dez 2016 14:08

AW: Multi-Event-Liste
 
Anhang?


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:08 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz