![]() |
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:
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).
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; 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 ? |
AW: Multi-Event-Liste
Bei dem Spring4D-Projekt gibt es so ein Ding.
|
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: ![]() 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 ? |
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:
Zum Testen verwendig ich folgenden Aufruf:
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;
Delphi-Quellcode:
TEventType5 ist so definiert:
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;
Delphi-Quellcode:
Soweit so gut. Leider Schepperts beim Aufruf der obigen Methode mit diesem EvenType. Benutze ich
TEventType5 = Procedure(v1:integer;v2:integer;v3:integer;v4:Widestring;v5:boolean;v6:double;v7:string;v8:widestring;v9:TTestRec;v10:integer) of object;
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 ? |
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 ![]() |
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:
Aufruf:
//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);
Delphi-Quellcode:
Das Problem ist der 3 Parameter im Array (also die 42), die wird einfach mit 0 übergeben. Der Rest passt.
fevents.Execute('TEventType6',[150,333,42,true,'Wuptidupti']);
|
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. |
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.
|
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.) |
AW: Multi-Event-Liste
Anhang?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:59 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz