Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Adresse eine Funktion / Prozedur ermitteln (https://www.delphipraxis.net/115619-adresse-eine-funktion-prozedur-ermitteln.html)

Fussball-Robby 15. Jun 2008 00:00


Adresse eine Funktion / Prozedur ermitteln
 
Ich möchte eine Funktion aufrufen, von der ich lediglich den Namen habe. Ich habe bereits die Funktion MethodAddress gefunden, die aber (wie der Name schon sagt) nut für Methoden funktioniert. Die Unit, in der ich das brauche, ist so aufgebaut:
Delphi-Quellcode:
unit unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

  type
    TMyProcedure = function(Value: String): String;

  function HandleValues(Value: String): String;

implementation

function HandleValues(CommandLine: String): String;
var
  Proc: TMyProcedure;
begin
  //??
end;

end.
Alle Funktionen sind gleich aufgebaut, undzwar so, wie TMyProcedure. Je nach dem, welcher Parameter jetzt der Funktion HandleValues übergeben wird, soll die Funktion mit dem entsprechenden Namen aufgerufen werden(Hab die Funktionen jetzt hier nicht mit reinkopiert).
Ist das irgendwie möglich? Wenn nicht, dann werde ich wohl jeden möglichen Paramter mit if abfragen müssen :?

omata 15. Jun 2008 00:04

Re: Adresse eine Funktion / Prozedur ermitteln
 
Schau dir mal den Befehl overload an.

Neutral General 15. Jun 2008 00:04

Re: Adresse eine Funktion / Prozedur ermitteln
 
Hi,

Soweit ich weiß, ist das nicht möglich. Denn MethodAddress arbeitet ja mit der RTTI, die ja für proceduren nicht gespeichert wird. Es sieht also meines Wissens schlecht für dich aus.

Gruß
Neutral General

Die Muhkuh 15. Jun 2008 00:06

Re: Adresse eine Funktion / Prozedur ermitteln
 
Zitat:

Zitat von omata
Schau dir mal den Befehl overload an.

Er will imho sowas erreichen:

Über CommandLine kommt z.B. -bla ?blubb

Dann will er procedure Bla mit Parameter blubb aufrufen.

Fussball-Robby 15. Jun 2008 00:07

Re: Adresse eine Funktion / Prozedur ermitteln
 
Zitat:

Zitat von omata
Schau dir mal dir mal den Befehl overload an.

Inwiefern soll ich den hier benutzuen? Ich will ja nicht eine Funktion mehrfach mit verschiedenen Parametern deklarieren, sondern jenachdem, was für ein String als Parameter übergeben wird, eine andere Funktion aufrufen.

Zitat:

Zitat von Neutral General
Soweit ich weiß, ist das nicht möglich. Denn MethodAddress arbeitet ja mit der RTTI, die ja für proceduren nicht gespeichert wird. Es sieht also meines Wissens schlecht für dich aus.

Hatte ich fast schon befürchtet :? Naja, dann mach ich mich mal ans if..then..else tippen.. Wenn jemand noch eine Idee hat, immer her damit.

omata 15. Jun 2008 00:11

Re: Adresse eine Funktion / Prozedur ermitteln
 
Ok, overload ist hier wohl nicht geeignet. Trotzdem würde ich nicht mit einen String arbeiten. Wie wäre es mit einem Aufzählungstyp? Ausserdem wieso programmierst du das nicht gleich in einer ordentlichen OOP-Struktur?
Aber wir wissen ja nicht was du da vorhast, wie auch immer viel Glück bei der Realisierung.

Fussball-Robby 15. Jun 2008 00:14

Re: Adresse eine Funktion / Prozedur ermitteln
 
OK, ganz kurze und grobe Erklärung von dem, was ich vorhabe: Beutzer gibt in ein Edit einen Befehl ein. Befehl wird weitergegeben an meine Funktion, Funktion ruft die Funktion auf, deren Name mit dem des eingegebenen Strings übereinstimmt.

Neutral General 15. Jun 2008 00:14

Re: Adresse eine Funktion / Prozedur ermitteln
 
Wären es Methoden einer Klasse (, die auch notfalls nur existiert um die procedure zu enthalten) dann hätte ich da was für dich :)

Fussball-Robby 15. Jun 2008 00:15

Re: Adresse eine Funktion / Prozedur ermitteln
 
Zitat:

Zitat von Neutral General
Wären es Methoden einer Klasse (, die auch notfalls nur existiert um die procedure zu enthalten) dann hätte ich da was für dich :)

Na dann schieß mal los :thumb:

Neutral General 15. Jun 2008 00:23

Re: Adresse eine Funktion / Prozedur ermitteln
 
Delphi-Quellcode:

type
  // Deine Proceduren
  TProceduren = class
  published
   // Die proceduren
   class procedure ShowString(S: String);
   // Damit werden sie aufgerufen:
   class procedure RunMethod(AMethod: String; Params: array of Const);
  end;

{ TProceduren }

class procedure TProceduren.RunMethod(AMethod: String;
  Params: array of Const);
var proc: Pointer;
    i, off: Integer;
    max: Integer;
begin
  proc := MethodAddress(AMethod);
  max := Length(Params);

  for i:= 2 to max-1 do
  begin
    off := i*8;
    asm
      mov edx,[Params]
      add edx,off

      movzx ecx,[edx+$04]
      mov edx,[edx]

      sub ecx,3
      jnz @NoExt
        movzx ecx, word ptr [edx+$08]
        push ecx
        push [edx+$04]
        push [edx]
        jmp @LoopEnd
      @NoExt:
        push [edx]
      @LoopEnd:
    end;
  end;

  asm
    mov eax, max
    and eax, eax
    jz @Self
    sub eax,1
    jz @Param1
@Param2:
    mov ecx, [Params];
    add ecx, 8

    movzx eax,[ecx+$04]

    mov ecx,[ecx]

    sub eax, 3
    jnz @Param1
      movzx eax, word ptr [ecx+$08]
      push eax
      push [ecx+$04]
      push [ecx]
@Param1:
    mov edx, [Params]

    movzx eax,[edx+$04]

    mov edx, [edx]

    sub eax, 3
    jnz @Self
      movzx eax, word ptr [edx+$08]
      push eax
      push [edx+$04]
      push [edx]
@Self:
    mov eax,Self

    call proc
  end;
end;

class procedure TProceduren.ShowString(S: String);
begin
  ShowMessage(S);
end;

// Anwendung:
procedure TForm1.Button1Click(Sender: TObject);
begin
  TProceduren.RunMethod('ShowString',['Hallo Welt']);
  TProceduren.RunMethod('ShowString',[Edit1.Text]);
end;
Übergeben werden kann prinzipell ein Array of TVarRec, dass du natürlich auch dynamisch erzeugen (vom Benutzer erzeugen/einstellen) lassen kannst.

Gruß
Neutral General

Fussball-Robby 15. Jun 2008 00:27

Re: Adresse eine Funktion / Prozedur ermitteln
 
Danke, werde ich mir morgen heute(so spät schon :cyclops: ) mal genauer angucken :wink:

Neutral General 15. Jun 2008 00:29

Re: Adresse eine Funktion / Prozedur ermitteln
 
Sag mir unbedingt obs läuft, notfalls schreib ich dir ne kleine Demo :)

Bin ganz stolz auf das Ding :mrgreen: Wobei ich gestehn muss, dass ich das ohne Apollonius nicht geschafft hätte. Der ASM Teil hat mir doch ab und zu zu schaffen gemacht *g*

Gruß
Neutral General

Fussball-Robby 15. Jun 2008 09:04

Re: Adresse eine Funktion / Prozedur ermitteln
 
Zitat:

Zitat von Neutral General
Sag mir unbedingt obs läuft, notfalls schreib ich dir ne kleine Demo :)

Läuft soweit, hab nur noch eine Prüfung auf proc = nil eingebaut, damit es keine AV gibt, wenn es die Methode nicht gibt :thumb: Was ich aber noch nicht ganz verstanden habe ist die Parameterübergabe mittels TVarRect... Vielleicht wäre eine kleine Demo oder eine Erklärung doch nicht so schlecht :wink:

Apollonius 15. Jun 2008 11:34

Re: Adresse eine Funktion / Prozedur ermitteln
 
Ich glaube, dass da noch ein paar Fehler drin sind. Teste das mal mit einer Prozedur, die Integer-Parameter entgegennimmt - ich denke, dass das bei @NoExt push edx statt push [edx] heißen muss.
Außerdem wird es unangenehm, wenn einer der ersten beiden nicht-Self-Parameter ein Float ist - dann wird nämlich der vierte Parameter in ecx übergeben, anstatt gepusht zu werden. Das macht es insgesamt äußerst kompliziert - vielleicht wäre es besser, stdcall, cdecl oder pascal als Aufrufkonvention zu verlangen.

Neutral General 15. Jun 2008 11:58

Re: Adresse eine Funktion / Prozedur ermitteln
 
Zitat:

Zitat von Apollonius
[...]Das macht es insgesamt äußerst kompliziert - vielleicht wäre es besser, stdcall, cdecl oder pascal als Aufrufkonvention zu verlangen.

Mh ja das könnte sein... Nur "damals" wäre stdcall für mich nicht so gut gewesen. Aber wenn man die Methode nur "für sich" braucht, dann wärs natürlich einfacher.

Ich gucke mir grad die Methode nochmal an. Vorallem die Stellen, die du genannt hast.

Gruß
Neutral General

Fussball-Robby 15. Jun 2008 15:58

Re: Adresse eine Funktion / Prozedur ermitteln
 
Wenn ihr hier über Assembler redet, ist das so als würde ich chinesisch rückwärts lesen :stupid: Ich sollte das vielleicht auch mal lernen, dann müsste ich jetzt nicht warten, bis das hier jemand nen verbesserten Code postet..

Neutral General 15. Jun 2008 16:03

Re: Adresse eine Funktion / Prozedur ermitteln
 
*hust* Wie bestellt ist hier auch schon der neue Code *g*

Delphi-Quellcode:
class procedure TProceduren.RunMethod(AMethod: String;
  Params: array of Const);
var proc: Pointer;
    hi: Integer;
    i, off: Integer;
    param: Byte;
begin
  proc := MethodAddress(AMethod);
  hi := High(Params);
  asm
    mov param,0
    mov i,0
    @loop:
      mov eax,i
      cmp eax,hi
      jg @loopend  
        imul eax,i,8
        add eax,4
        mov off,eax
         
        mov eax,[Params]
        add eax,off
        movzx ax,byte ptr [eax]
         
        cmp ax,vtExtended
        je @EditParam
          inc param
          cmp param,2
          jle @NextLoop
        @EditParam:
          sub off,4
          cmp ax,vtExtended
          jne @NoExt
            mov eax,[Params]
            add eax,off
            mov eax,[eax]
            movzx edx, word ptr [eax+$08]
            push edx
            push [eax+$04]
            push [eax]
            jmp @NextLoop
          @NoExt:
            mov eax,[Params]
            add eax,off
            push [eax]
        @NextLoop:
          inc i
          jmp @loop
    @loopend:

    mov param,0
    mov i,0
    @loop2:
      mov eax,i
      cmp eax,hi
      jnl @loop2end
        imul eax,i,8
        add eax,4
        mov off,eax
       
        mov eax,[Params]
        add eax,off
        mov eax,[eax]

        cmp eax,vtExtended
        je @NextLoop2
        inc param

        cmp param,1
        je @edx
        cmp param,2
        je @ecx
        jmp @loop2end

        @edx:
          sub off,4
          mov eax,[Params]
          add eax,off
          mov edx,[eax]
          jmp @NextLoop2
        @ecx:
          sub off,4
          mov eax,[Params]
          add eax,off
          mov ecx,[eax]
          jmp @Loop2End
      @NextLoop2:
        inc i
        jmp @loop2
    @loop2end:

    mov eax,self
    call proc
  end;
end;
Int64's werden jedoch noch nicht unterstützt. Ich arbeite aber daran ;)

Gruß
Neutral General

Fussball-Robby 15. Jun 2008 17:05

Re: Adresse eine Funktion / Prozedur ermitteln
 
Ich bin hier gerade am verzweifeln.. :?
Ich bekomm es einfach nicht hin, dass die Prozedur ShowString den Parameter mittes ShowMessage richtig ausgibt..Mal gibts ne AV, mal kommt ne leere MessageBox... Könntest du mir villeicht ein kleines Demo machen, ich kriegs einfach nicht hin :wall:

Neutral General 15. Jun 2008 18:31

Re: Adresse eine Funktion / Prozedur ermitteln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hab dir mal eine Demo angehängt. Hab auch noch einen Fehler korrigiert und die Methode kann jetzt alles außer Variants.

Hier nochmal der komplette Quelltext:
Delphi-Quellcode:
type
  TProcedures = class
  published // Oder Public, dann muss aber der Compilerschalter {$METHODINFO ON} aktiviert sein
    class procedure ShowString(S: String);
    class procedure MegaTest(a: Integer; b: Boolean; c: Char; d: Extended; e: String; f: Pointer;
                             g: PChar; h: TObject; i: TClass; j: WideChar; k: PWideChar;
                             l: AnsiString; m: Currency; n: IUnknown;
                             o: WideString; p: Int64);
    class procedure RunMethod(AMethod: String; Params: Array of Const);
  end;

implementation

class procedure TProcedures.RunMethod(AMethod: String;
  Params: Array of Const);
var proc: Pointer;
    hi: Integer;
    i, off: Integer;
    param: Byte;
begin
  proc := MethodAddress(AMethod);
  hi := High(Params);
  asm
    mov param,0
    mov i,0
    @loop:
      mov eax,i
      cmp eax,hi
      jg @loopend
        imul eax,i,8
        add eax,4
        mov off,eax

        mov eax,[Params]
        add eax,off
        movzx ax,byte ptr [eax]

        cmp ax,vtExtended
        je @EditParam
          cmp ax,vtInt64
          je @EditParam
          cmp ax,vtCurrency
          je @EditParam
          inc param
          cmp param,2
          jle @NextLoop
        @EditParam:
          sub off,4
          cmp ax,vtExtended
          jne @NoExt
            mov eax,[Params]
            add eax,off
            mov eax,[eax]
            movzx edx, word ptr [eax+$08]
            push edx
            push [eax+$04]
            push [eax]
            jmp @NextLoop
          @NoExt:
            cmp ax,vtInt64
            je @Int64Currency
            cmp ax,vtCurrency
            je @Int64Currency
            cmp ax,vtChar
            je @Char
            @Standard:
              mov eax,[Params]
              add eax,off
              push [eax]
              jmp @NextLoop
            @Char:
              mov eax,[Params]
              add eax,off
              mov eax,[eax]
              xor edx,edx
              mov dl,al
              push edx
              jmp @NextLoop
            @Int64Currency:
              mov eax,[Params]
              add eax,off
              mov eax,[eax]
              push [eax+$04]
              push [eax]
        @NextLoop:
          inc i
          jmp @loop
    @loopend:

    mov param,0
    mov i,0
    @loop2:
      mov eax,i
      cmp eax,hi
      jg @loop2end
        imul eax,i,8
        add eax,4
        mov off,eax

        mov eax,[Params]
        add eax,off
        movzx ax,byte ptr [eax]

        cmp ax,vtExtended
        je @NextLoop2
        cmp ax,vtInt64
        je @NextLoop2
        cmp ax,vtCurrency
        je @NextLoop2
       
        inc param

        cmp param,1
        je @edx
        cmp param,2
        je @ecx
        jmp @loop2end

        @edx:
          sub off,4
          mov eax,[Params]
          add eax,off
          mov edx,[eax]
          jmp @NextLoop2
        @ecx:
          sub off,4
          mov eax,[Params]
          add eax,off
          mov ecx,[eax]
          jmp @Loop2End
      @NextLoop2:
        inc i
        jmp @loop2
    @loop2end:

    mov eax,Self
    call proc
  end;
end;

class procedure TProcedures.ShowString(S: String);
begin
  ShowMessage(S);
end;

class procedure TProcedures.MegaTest(a: Integer; b: Boolean; c: Char; d: Extended;
  e: String; f: Pointer; g: PChar; h: TObject; i: TClass; j: WideChar;
  k: PWideChar; l: AnsiString; m: Currency; n: IInterface;
  o: WideString; p: Int64);
begin
  ShowMessage(Format('a: %d'#13#10 // Integer
                   + 'b: %d'#13#10 // Boolean (auf Integer gecastet)
                   + 'c: %s'#13#10 // Char
                   + 'd: %f'#13#10 // Extended (Single,Double)
                   + 'e: %s'#13#10 // String
                   + 'f: %p'#13#10 // Pointer
                   + 'g: %s'#13#10 // PChar
                   + 'h: %s'#13#10 // TObject (Classname)
                   + 'i: %s'#13#10 // TClass (Classname)
                   + 'j: %d'#13#10 // WideChar
                   + 'k: %s'#13#10 // PWideChar
                   + 'l: %s'#13#10 // AnsiString
                   + 'm: %f'#13#10 // Currency
                   + 'n: %d'#13#10 // Interface
                   + 'o: %s'#13#10 // WideString
                   + 'p: %d'#13#10,// Int64
                   [a,Integer(b),c,d,e,f,g,h.ClassName,i.ClassName,Word(j),k,l,m,Integer(n),o,p]));
end;
Aufruf:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  TProcedures.RunMethod('ShowString',['Test']);
end;

// Der utlimative Test/Beweis für das funktionieren meiner Methode :P
// Gibt man konkrete Werte an, muss z.T. gecastet werden, da der Compiler
// z.B. 123456789 ohne den Cast auf Int64 als normalen Integer behandelt
// ==> Exception!
// Man muss halt entweder casten oder int64 variablen etc übergeben.
// Das gleiche gilt auch noch für ein paar andere Typen, aber das kann man unten
// ja ablesen
//
// PS: Das bei dem Interface '0' angezeigt wird, ist schon richtig so ;)
procedure TForm1.Button2Click(Sender: TObject);
var x: IUnknown;
    curr: Currency;
    pwc : PWideCHar;
begin
  curr := 999;
  pwc := 'WideChar Welt';
  TProcedures.RunMethod('MegaTest',[22,true,'c',123.456,'Hallo Welt',Pointer($ABCDEF),
                        'Hallo Welt 2',Form1,TButton,WideChar('w'),pwc,
                        'En Ansistring',curr,x,WideString('B r e i t e r S t r i n g *g*'),
                         Int64(123456789)]);
end;
Gruß
Neutral General

BlueWonder 20. Jun 2008 10:44

Re: Adresse eine Funktion / Prozedur ermitteln
 
Ich hätte da noch eine etwas einfachere Lösung. :-D Also ohne Assembler. :zwinker: Dabei stellt "TDynMethod" die Signatur der aufzurufenden Methoden dar und die Adresse der gesuchten Methode kommt in eine Variable vom Typ "TMethod" und wird anschließend in den Typ "TDynMethod" gecastet und hier auch gleich ausgeführt. Hab allerdings nicht explizit alle Datentypen durchprobiert. Da der Auffruf aber nicht aus der Applikation raus geht, sollten eigentlich alle Parameter-Typen funktionieren.

Delphi-Quellcode:
unit Unit3;

{$METHODINFO ON}

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  TDynMethod = function(s: String):String of object;

  TForm3 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure execMyMethod(name: String);
    function m1(value: String): String;
    function m2(value: String): String;
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}


procedure TForm3.execMyMethod(name: string);
var
  dMethode: TMethod;
begin
  dMethode.Data := Self;                     // Objekt zu dem die Methode gehört
  dMethode.Code := Self.MethodAddress(name); // Adresse der gesuchten Methode
  if (dMethode.Code <> nil) then
    ShowMessage(TDynMethod(dMethode)('Teststring')) // Type-Cast und sofortiger Aufruf mit einem sinnlosen String :)
  else
    ShowMessage('Die angegebene Methode wurde nicht gefunden!');
end;


function TForm3.m1(value: string): String;
begin
  Result := 'Ich bin Methode 1 und übergeben wurde: ' + value;
end;


function TForm3.m2(value: string): String;
begin
  Result := 'Ich bin Methode 2 und übergeben wurde: ' + value;
end;


procedure TForm3.Button1Click(Sender: TObject);
begin
  execMyMethod(Edit1.Text);
end;

end.

Neutral General 20. Jun 2008 11:26

Re: Adresse eine Funktion / Prozedur ermitteln
 
Klar, aber das funktioniert nur wenn die Signatur der Methoden immer gleich ist.

Wenn du ne Methode hast in der ein Integer übergeben wird statt einem String oder mehrere Parameter dann stößt du damit schnell an Grenzen.

taaktaak 20. Jun 2008 11:40

Re: Adresse eine Funktion / Prozedur ermitteln
 
Moin, Moin,
mal die vermutlich geniale technische Lösung ausser Acht gelassen:

Ich habe (sofern ich die Aufgabenstellung richtig verstanden habe) Zweifel am Grundkonzept. Der Anwender soll im Freitext den Namen einer fest verdrahteten Func/Proc eingeben, die dann aufgerufen wird? Seltsam!

Da der "Befehlsvorrat" fest vorgegeben ist, wäre es doch viel effizienter wenn der Anwender aus dem Befehlsvorrat auswählen könnte. Also Listbox, Combobox - whatever. Das ist schneller, einfacher und schließt Fehler aus.

BlueWonder 20. Jun 2008 11:53

Re: Adresse eine Funktion / Prozedur ermitteln
 
@NeutralGeneral:
Nach etwas grübeln, versteh ich jetzt glaub was du meinst. Jetzt steig ich auch langsam dahinter, was der ASM-Code genau bewirkt. :idea: Muss ich zugeben, is ne clevere Sache. :thumb: Bei mir hat es bisher diese Unterschiede so nich gegeben, deswegen reichte mir eine feste Signatur, wo eben nur jede Methode ihre spezielle Arbeit verrichtet. Dann möchte ich mich für meinen Post entschuldigen und den mal so als Alternative für simple Sachen stehen lassen. :?

@taaktaak:
Der Sinn dieser ganzen Sache kann sich über mehrere Bereiche Verteilen. Zum Beispiel kann in ein Programm eine Art Konsole eingebaut werden, in welcher der Benutzer Befehle eintippen kann, die dann ausgeführt werden. (wie zb. "clear" um den Inhalt zu löschen) Der Funktionsumfang könnte durchaus so groß werden, dass er in List-Boxen nicht mehr recht überschaubar wäre. Außerdem verstößt das gegen das Grundlayout einer Konsole. :wink:
Oder aber das Programm bekommt ein Objekt übergeben, von dem es die genaue Klassenbeschreibung nicht kennt. Wohl aber weiß oder mitgeteilt bekommt, dass dieses Objekt die Methode "bla" enthält und diese Aufzurufen ist.

Neutral General 20. Jun 2008 12:39

Re: Adresse eine Funktion / Prozedur ermitteln
 
Hi BlueWonder,

Brauchst dich nicht zu entschuldigen ;) Hast mich ja nicht irgendwie angegriffen oder so :cheers:

Gruß
Neutral General

Vjay 20. Jun 2008 13:09

Re: Adresse eine Funktion / Prozedur ermitteln
 
Hi, mal eine Frage dazu ob das prinzipiell möglich ist.

Ich habe schon lange mal vorgehabt (ist halt immer an keiner Zeit oder Faulheit gescheitert) ein Programm zu schreiben, welches auf Plugins und Events basiert und deren SInn es ist diese zusammen zu bringen. Ein Beispiel, es gibt eine DLL, welche Hooking benutzt um den Fenstermanager zu überwachen bzw. Events zu abonieren in der DLL, andererseits stellt sie Funktionen bereit um z.B. Mausklicks oder Tastatureingaben zu simulieren (diese bräuchten z.B. ein Handle als Ausgangsbasis). Nun hat man z.B. dieses Windowplugin, ein http Plugin, ein Comportplugin, ein Timerplugin, ein Systemplugin, ein Dateiplugin, etc pp.

Jetzt habe ich als Benutzer der Anwendung das spontane Problem, dass ich als Beispiel auf einen langen Download warten muss und ins Bett möchte. Also öffne ich schnell das Einstellungsfenster des Programms, ziehe ein Event vom Windowplugin hinein, lege fest, ich möchte Informiert werden wenn ein Fenster geschlossen wird, lege als Filter die Caption fest, ziehe das Herunterfahren Symbol vom Systemplugin hinein, sage herunterfahren + ausschalten und verknüpfe diese beiden Symbole und fertig.

So, ewig lange ausgeholt, tut mir leid. Das Problem an der Geschichte ist bisher, dass einige Funktionen ja Übergabeparameter erwarten/zurückliefern, wie ein Fensterhandle z.B. Diese müsste man ja quasi mitverknüpfen. Als Beispiel WindowEventFensterGeöffnet(HWND)->SimuliereMausklickAufFenster(HWND) oder WindEventFensterGeöffnet(HWND)->FindWindowObjekt(HWND)->SimuliereMausklickAufFenster(HWND) um woanders hin zu klicken.

Ist es irgendwie möglich Prozeduren währned der Laufzeit in diese Richtung zu analysieren welche Parameter sie erwarten? Es müssten ja (automatisiert) Zuweisungen und evtl sogar impliziert Typecasts erfolgen. Ich hatte damals(5 Jahre etwa) mit Variants mal gestartet, aber abgebrochen, da es in unendliche Komplexität ausgeartet ist.

uligerhardt 20. Jun 2008 13:10

Re: Adresse eine Funktion / Prozedur ermitteln
 
Zitat:

Zitat von Fussball-Robby
Naja, dann mach ich mich mal ans if..then..else tippen.. Wenn jemand noch eine Idee hat, immer her damit.

Ich würde statt einer if-then-else-Wüste eine TStringList o.ä. nehmen, bei der du die Prozedurzeiger in .Objects reinstopfst.

HTH,
Uli.

Neutral General 20. Jun 2008 13:27

Re: Adresse eine Funktion / Prozedur ermitteln
 
Zitat:

Zitat von Vjay
Ist es irgendwie möglich Prozeduren währned der Laufzeit in diese Richtung zu analysieren welche Parameter sie erwarten? Es müssten ja (automatisiert) Zuweisungen und evtl sogar impliziert Typecasts erfolgen. Ich hatte damals(5 Jahre etwa) mit Variants mal gestartet, aber abgebrochen, da es in unendliche Komplexität ausgeartet ist.

Hi,

ja das dürfte mit der erweiterten RTTI möglich sein. Musst du mal im Forum nach suchen. Naja wenn du die Parameter herausgefunden hast, musst du die Procedure ja auch irgendwie aufrufen. Das ginge ja eventuell mit meiner Methode aber ich bräuchte glaube ich mehr Infos wie das ganze ablaufen soll...

Vjay 20. Jun 2008 13:46

Re: Adresse eine Funktion / Prozedur ermitteln
 
Hmh stimmt, das könnte ansich schon funktionieren.
Erschwerend wäre nur vielleicht, dass alles dezentral über DLLs verteilt ist.

Nunja ich hatte mir das so gedacht, wie im obigen Beispiel, dass man in der Window-DLL ein Event registriert und als Empfängerfunktion gleich die Adresse der SystemDLL-Herunterfahren Funktion hinterlegt. Ich bin kein Fan von Parsern oder sonstigen Geraffel. So hätte man maximale Performance, also auch für Events die sehr sehr oft kommen. Nur irgendwo müsste da ein intelligentes Stück Code dazwischen, welches erkennt, dass die eine funktion ein outHWND liefert und die andere in diesem Fall einen inHWND benötigt und dann deinen Code verwendet und die Funktion richtig aufruft.

Gedankengang der Unternehmung war es im Grunde, die kleinen Programme, die wir Programmierer für kleine Aufgaben schreiben überflüssig zu machen und es damit auch der breiten Masse zugänglich zu machen.
Wie wenn man mal eben schnell nen Portforwarding braucht, Einstellungen öffnen, NetzwerkDLL Server, Client IP + Ports rein, Linie ziehen - fertig, evtl. LogDatei noch dazwischenhängen.

MSSSSM 18. Dez 2008 19:33

Re: Adresse eine Funktion / Prozedur ermitteln
 
Tut mir leid, dass ch diesen Thread wieder ausgrabe, aber müssen die Prozeduren class procedure s sein?
Weil ich wollte nämlich einen XUL-Parseer bauen, und da sollten sich die Funktionen in die Form integrieren lassen.

(Link: XUL-Engine )

Neutral General 18. Dez 2008 21:22

Re: Adresse eine Funktion / Prozedur ermitteln
 
Nein, sie müssen keine Class-proceduren sein, aber sie müssen halt published sein, oder bei MethodInfo ON zumindest public (Soweit ich weiß, aber ich hab grad kein Delphi und bin mir nicht sicher)

Cyf 18. Dez 2008 22:40

Re: Adresse eine Funktion / Prozedur ermitteln
 
Also - wenn man mal außer acht lässt, dass das asm-Konstrukt viel ästhetischer ist - was spricht hier eigentlich dagegen, mit den Prozedurnamen einen enum-Typ zu erstellen und beim Programmstart alle möglichen Einsprungspunkte der Prozeduren in ein Array zu packen? Für die Überprüfung bräuchte man dann noch ein zweites Array in dem die vom Benutzer zu benutzenden Befehle (also die Funktionsnamen), als Textstrings an den Indexen die dem enum-Typ entsprechen geparkt sind und schon muss man nur den übereinstimmenden Index suchen und springt dann an den Einsprungspunkt mit dem selben Index. Das hat die Vorteile, dass man bestimmen kann welche Funktionen zugänglich sein sollen (vom Benutzer) und welche nicht, es einfach zu handhaben ist und man die Funktionen ggf. intern anders nennen kann, als sie später von außen heißen sollen. Der einzige Nachteil der mir einfällt, sind 2 Zeilen Typarbeit und vielleicht 20 Byte Speicherverbrauch pro Funktion.
Ansonsten lagert man das ganze eben in Dlls aus, da kann man dann direkt nach dem Namen suchen und hängt die ggf. als Ressource an, wenn man wirklich eine umfangreiche Funktionsmenge bereitstellen will, macht das ohne hin Sinn, da der User wohl kaum immer alle brauchen wird.
Entschuldigt wenn das etwas verwirrend geschrieben ist, ist bisschen spät und ich bin jetzt weg. :-D

himitsu 19. Dez 2008 08:34

Re: Adresse eine Funktion / Prozedur ermitteln
 
man kann auch in einer EXE eine Funktion/Prozedur als External definieren (halt so wie bei einer DLL)

ich weiß jetzt nicht, wie leicht es dann ist die Adressen umzurechnen (falls man due Funktion direkt in der EXE aufrufen will), aber die EXE läßt sich notfalls wie eine DLL einbinden (mit ein paar kleinen Anpassungen)

static_cast 10. Dez 2013 13:25

AW: Re: Adresse eine Funktion / Prozedur ermitteln
 
Hallo,

gibt es von der "RunMethod" eine x64 Implementierung die auch mit XE5 laufen würde? Ich verwende Sie für diverse zwecke in meiner Anwendung, jedoch wollte ich diese nun in XE5 als 64Bit kompilieren und komme da nicht voran.

Viele Grüße
Daniel

Zitat:

Zitat von Neutral General (Beitrag 790864)
*hust* Wie bestellt ist hier auch schon der neue Code *g*

Delphi-Quellcode:
class procedure TProceduren.RunMethod(AMethod: String;
  Params: array of Const);
var proc: Pointer;
    hi: Integer;
    i, off: Integer;
    param: Byte;
begin
  proc := MethodAddress(AMethod);
  hi := High(Params);
  asm
    mov param,0
    mov i,0
    @loop:
      mov eax,i
      cmp eax,hi
      jg @loopend  
        imul eax,i,8
        add eax,4
        mov off,eax
         
        mov eax,[Params]
        add eax,off
        movzx ax,byte ptr [eax]
         
        cmp ax,vtExtended
        je @EditParam
          inc param
          cmp param,2
          jle @NextLoop
        @EditParam:
          sub off,4
          cmp ax,vtExtended
          jne @NoExt
            mov eax,[Params]
            add eax,off
            mov eax,[eax]
            movzx edx, word ptr [eax+$08]
            push edx
            push [eax+$04]
            push [eax]
            jmp @NextLoop
          @NoExt:
            mov eax,[Params]
            add eax,off
            push [eax]
        @NextLoop:
          inc i
          jmp @loop
    @loopend:

    mov param,0
    mov i,0
    @loop2:
      mov eax,i
      cmp eax,hi
      jnl @loop2end
        imul eax,i,8
        add eax,4
        mov off,eax
       
        mov eax,[Params]
        add eax,off
        mov eax,[eax]

        cmp eax,vtExtended
        je @NextLoop2
        inc param

        cmp param,1
        je @edx
        cmp param,2
        je @ecx
        jmp @loop2end

        @edx:
          sub off,4
          mov eax,[Params]
          add eax,off
          mov edx,[eax]
          jmp @NextLoop2
        @ecx:
          sub off,4
          mov eax,[Params]
          add eax,off
          mov ecx,[eax]
          jmp @Loop2End
      @NextLoop2:
        inc i
        jmp @loop2
    @loop2end:

    mov eax,self
    call proc
  end;
end;
Int64's werden jedoch noch nicht unterstützt. Ich arbeite aber daran ;)

Gruß
Neutral General


Neutral General 10. Dez 2013 14:59

AW: Adresse eine Funktion / Prozedur ermitteln
 
Hallo,

Also bisher nicht. Es sollte in 64Bit auch machbar sein, aber ich weiß halt nicht ob da die Parameter genauso abgelegt werden wie bei 32 Bit und die Register müssten angepasst werden..

Also wenn sich jemand freiwillig dran setzen will, dann kann er das gerne tun.
Generell würd ichs auch machen aber ich weiß nicht ob ich die Zeit dazu aufbringen kann/will.

Müsste mich auch erstmal wieder bisschen in ASM einarbeiten^^

himitsu 10. Dez 2013 15:00

AW: Adresse eine Funktion / Prozedur ermitteln
 
Wenn ich es richtig im Kopf hab, dann gibt es in Win64 kein Inline-Assembler mehr.

- entweder die Funktion in Pascal umwandeln (wird nicht einfach)
- oder diese "komplett" als Assembler, also auch
Delphi-Quellcode:
proc := MethodAddress(AMethod); hi := High(Params);
(natürlich via IFDEFs für x86 und x64)
- oder mal versuchen das über die neue RTTI zu lösen

static_cast 10. Dez 2013 16:58

AW: Adresse eine Funktion / Prozedur ermitteln
 
Hallo und danke euch zwei für die Antworten ;)

Dachte mir schon das es nicht so einfach ist, aber fragen kostet ja nichts ^^ und da ich jetzt auch kein ASM-Crack bin versuch ich das dann wohl anders umzusetzen, oder ich lass es so und es gibt halt kein x64 build :D

Viele Grüße
Daniel


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:33 Uhr.

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