![]() |
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?
|
AW: Multi-Event-Liste
Liste der Anhänge anzeigen (Anzahl: 1)
Ja...kommt gleich....Browser streikt grad :)
So..da isser :) Edit1: Zip updated: enthält jetzt auch die DFM Edit2: HINWEIS: Das Projekt verwendet FastMM4 ! |
AW: Multi-Event-Liste
dfm fehlt.
|
AW: Multi-Event-Liste
gefixt.
|
AW: Multi-Event-Liste
Bedenke übrigens, dass der Code ab Delphi 2009 grandios in die Luft fliegen wird, weil dort teilweise mit PChar statt PByte gearbeitet wird und die RTTI erweitert wurde - weitere virtuelle Methoden in TObject etc)
|
AW: Multi-Event-Liste
Ich weiß.
Sobald ich eine neuere Delphi Version in die Finger bekomm, kann ich das entsprechend anpassen. |
AW: Multi-Event-Liste
Ich würde übrigens statt strings als ident den PTypeInfo der events nutzen.
|
AW: Multi-Event-Liste
Zitat:
In Delphi 2006 / Turbo Delphi wurde der DelphiMM durch eine angepasste Version des FastMM ersetzt. (nur abgesehn von ![]() Zitat:
![]() |
AW: Multi-Event-Liste
@Stevie
Jaein. Ich muss zumindest die Info mit in der Liste verwalten, damit ich die Parameterliste des Events mit der Parameterliste des Eventhandlers abgleichen kann (und ggf. mit der beim Aufruf übergebenen Parametern) prüfen kann. hmmm.....da werd ich wohl um ein redesign des ganze nicht ganz rumkommen. Der String ist letztlich nur eine ID, die den Code etwas lesbarer macht :) @Himitsu Ja, deswegen verwende ich das "orginal", wegen Debugging/MemoryLeaks. Das erleichtert die Entwicklung doch ungemein. und im Release sollte es normal keinen großen Unterschied machen. Jup..ich weiß. Aber mit XP komm ich da nicht weit :) d.h. Ich müsste mich erstmal dazu durchringen, alle Daten von der Kiste zu sichern, die Kiste platt machen und win7 (öhm...würde das überhaupt ausreichen ?) draufpacken. Summa sumarum erst mal 2-3 Tage arbeit. |
AW: Multi-Event-Liste
Windows 7 wird noch von der IDE unterstützt.
|
AW: Multi-Event-Liste
Zitat:
Delphi-Quellcode:
als das
fevents.Execute(TypeInfo(TEventType5),[150,333,42,'Schweine im Weltraum oder Trampen leicht gemacht',FALSE,1.5647,'Normal String','Another very wide String',@rec,2357]);
Delphi-Quellcode:
Ganz im Gegenteil, wenn ich mich irgendwo vertippt habe oder ein Eventtyp umbenannt habe, dann gibts nen Compilerfehler, wohingegen beim String irgendwas zur Laufzeit schief laufen kann und erstmal Fehlersuche erforderlich macht.
fevents.Execute('TEventType5',[150,333,42,'Schweine im Weltraum oder Trampen leicht gemacht',FALSE,1.5647,'Normal String','Another very wide String',@rec,2357]);
|
AW: Multi-Event-Liste
hmmm....da hast jetzt auch wieder recht.
|
AW: Multi-Event-Liste
Liste der Anhänge anzeigen (Anzahl: 1)
Sooo....feddich.
Mit ein paar Einschränkungen funktioniert das ganze jetzt. :) Einschränkungen: Gleitkommawerte (Floats): Da Delphi intern alles auf Extended castet, kann die Liste nur Parameter als Extended (od. Currency) handhaben. Objectinstanzen, Interfaces und Klassen: Werden als VAR-Parameter immer als Pointer zurückgegeben. Hab noch keine Idee wie man das eventuell umgehen kann. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:58 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-2025 by Thomas Breitkreuz