Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Funktionszeiger in StringList.Objects speichern und nutzen (https://www.delphipraxis.net/143613-funktionszeiger-stringlist-objects-speichern-und-nutzen.html)

Master_BB 19. Nov 2009 10:12


Funktionszeiger in StringList.Objects speichern und nutzen
 
Hallo,
Ich würde gerne in einer TStringList per AddObject('SomeStr', @ReadBla); hinzufügen
ReadBla ist definiert als function ReadBla(AItem, BItem : Tobject) :boolean.

Der Aufruf AddObject wie oben funktioniert nicht. Also Baue ich folgendes

TReadMethod = function(A, B : TObject) : boolean of object;

dann

Delphi-Quellcode:
var
  AMethod : TReadMethod;
begin
  AMethod := ReadBla;
  AStringList.AddObject('Bla', AMethod);
end;
Das funktioniert, obwohl ich mir nicht sicher bin ob AMethod wirklich ein Object ist.
Jetzt habe ich das Problem wie rufe ich AMethod aus AStringList auf?

Delphi-Quellcode:
  (AStringList.objects[0] as TReadMethod)(AObject, BObject); //FUNKTIONIERT NICHT!
Wenn mir da jemand weiterhelfen könnte wäre das sehr schick.

Gruß

wicht 19. Nov 2009 10:21

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Mahlzeit!

Warum muss es denn eine TStringList sein? Ist das nicht irgendwie... pervers :) ? Nichts für ungut :stupid: ..

himitsu 19. Nov 2009 10:21

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Sowas geht nicht "direkt", denn function of object ist kein "einfacher" Prozedur-Zeiger, sondern er ist ein Methoden-Zeiger und besteht eigentlich aus 2 Zeigern ala 8 Byte (einmal auf die Funktion und dann nocheiner zum Objekt)

Also paßt er nicht in einen "normalen" 4-Byte-Zeiger rein.


Du müßtest dir z.B. mit Delphi-Referenz durchsuchenNew Speicher für einen Metodenzeiger reservieren und den Zeiger zu diesem Speicher dann der Liste hinzufügen.

Master_BB 19. Nov 2009 10:26

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
puh,
schade, nagut dann baue ich ein Object dessen Eigenschaft den Zeiger beinhaltet und packe das dort rein.
Thx für die schnellen Antworten

Master_BB 19. Nov 2009 10:37

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
@himitsu

Hey ich probiere gerade deine Methode über new aus.
Also Definiere ich
Delphi-Quellcode:
var
  ARead : ^TReadMethod;
begin
  New(ARead);
  ARead^ := ReadBla;
  AStringList.AddObject('Bla', ARead);
end;
Wie Rufe ich die ganze Sache jetzt auf?
TReadMethod(AStringList.Objects[0])^(A,B) funktioniert nicht

mleyen 19. Nov 2009 10:40

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Müsste das nicht so heißen: "TReadMethod(Pointer(AStringList.Objects[0])^)(A,B)" :gruebel:
(Kann´s gerade nicht testen)

DeddyH 19. Nov 2009 10:41

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Kann man Methoden überhaupt ohne Objekt aufrufen?

Master_BB 19. Nov 2009 10:48

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Die Methode ReadBla ist innerhalb des Objektes definiert, also existiert ja ein Objekt.

@mleyen ja das könnte vlt funktionieren aber ich sehe gerade das
die Zuweisung

AStringList.AddObject('Bla', ARead);

nicht funktioniet. ARead ist für ihn kein Objekt.
Habe ARead nach dem new Beispiel folgendermaßen definiert
Delphi-Quellcode:
TReadMethod = function(A, B : TObject) : boolean of object;
PReadMethod = ^TReadMethod
...
var
  ARead : PReadMethod

DeddyH 19. Nov 2009 10:56

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Wieso fügst Du dann nicht das Objekt in die Liste ein statt "mit Gewalt" nur dessen Methode?

himitsu 19. Nov 2009 11:01

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
das Zuweisen das ist schonmal OK
Delphi-Quellcode:
var
  ARead : PReadMethod;
begin
  New(ARead);
  ARead^ := ReadBla;
  AStringList.AddObject('Bla', ARead);
end;
das Auslesen einfach so
Delphi-Quellcode:
PReadMethod(AStringList.Objects[0])^
Und am Ende nicht das Freigeben (Dispose) vergessen.


@DeddyH: wenn er :=ReadBla nutzt, dann wird dieser Code vermutlich direkt in der Klasse ( :=Self.ReadBla ) rumliegen ... also kein Problem :)

uligerhardt 19. Nov 2009 11:29

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Zitat:

Zitat von himitsu
@DeddyH: wenn er :=ReadBla nutzt, dann wird dieser Code vermutlich direkt in der Klasse ( :=Self.ReadBla ) rumliegen ... also kein Problem :)

Wenn das so wäre, dann könnte man sich das Gezuchtel mit New und Dispose sparen, und doch nur den 4-Byte-Funktionszeiger (TMethod.Code) verwenden:
Delphi-Quellcode:
  TMyClass = class
  strict private
    FStringList: TStringList;
    function ReadBla(AItem, BItem: TObject): Boolean;
    procedure Rein(const AName: string; const AReadMethod: TReadMethod);
    function Raus(AIndex: Integer; AItem, BItem: TObject): Boolean;
  public
    constructor Create;
    procedure Test;
  end;

constructor TMyClass.Create;
begin
  inherited Create;
  FStringList := TStringList.Create;
end;

procedure TMyClass.Test;
begin
  Rein('Bla', ReadBla);
  if not Raus(0, nil, nil) then
    Beep;
end;

procedure TMyClass.Rein(const AName: string; const AReadMethod: TReadMethod);
var
  AMethod: TMethod;
begin
  TReadMethod(AMethod) := AReadMethod;
  FStringList.AddObject(AName, AMethod.Code);
end;

function TMyClass.Raus(AIndex: Integer; AItem, BItem: TObject): Boolean;
var
  AMethod: TMethod;
begin
  AMethod.Data := Self;
  AMethod.Code := FStringList.Objects[AIndex];
  Result := TReadMethod(AMethod)(AItem, BItem);
end;

alzaimar 19. Nov 2009 13:24

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
So: (OOP)
Delphi-Quellcode:
Type
  TSomeFunction = Function (A,B : TSomeType) : TSomeResult;
  TMetaFunction = Class
  Private
    fFunction : TSomeFunction;
  Public
    Constructor Create (aFunction : TSomeFunction);
    Function CallFunction (A,B : TSomeType) : TSomeResult;
  End;

Constructor TMetaFunction.Create(aFunction : TSomeFunction);
Begin
  fFunction := aFunction;
End;

Function TMetaFunction.CallFunction (A,B : TSomeType) : TSomeResult;
Begin
  Result := fFunction (A,B);
End;
...

  MyFunctions.Add('FooBarFunction', TMetaFunction.Create(@FooBar)); // Muss man nur beim Aufräumen aufpassen.

  MyResult := TMetaFunction(MyFunctions.Objects[MyFunctions.IndexOf('FooBarFunction')]).CallFunction(A,B);
Oder so (QAD):
Delphi-Quellcode:
Var
  FunctionNames : TStringList;
  FunctionPointer : TList;

Procedure AddFunction (aName : String; aFunction : TSomeFunction);
Begin
  FunctionNames.Add(aName);
  FunctionPointer.Add(aFunction);
End;

Function GetFunction (aName : String) : TSomeFunction;
Begin
  Result := TSomeFunction(FunctionPointer[FunctionName.IndexOf(aName)]);
End;
...
AddFunction ('FooBarFunction', @FooBar);
MyResult := GetFunction('FooBarFunction')(A,B);
@uligerhard: Wegen deiner komischen Bezeichner (Rein, Raus) verstehe ich deinen Code nicht. Machst du das immer so?

uligerhardt 19. Nov 2009 13:34

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Zitat:

Zitat von alzaimar
@uligerhard: Wegen deiner komischen Bezeichner (Rein, Raus) verstehe ich deinen Code nicht. Machst du das immer so?

In "echtem" Code verwende ich natürlich andere Namen. Aber für das Beispiel (Methode rein in die Stringliste, Methode wieder rausholen) erschienen mir Rein/Raus recht aussagekräftig - offensichtlich eine Fehleinschätzung. Andererseits ist der Code ja jetzt wirklich nicht so kompliziert, dass meine "Obfuskation" dir keine Chance zum Durchsteigen lässt.

uligerhardt 19. Nov 2009 13:47

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Zitat:

Zitat von alzaimar
Delphi-Quellcode:
Type
  TSomeFunction = Function (A,B : TSomeType) : TSomeResult;

Zitat:

Zitat von Master_BB
TReadMethod = function(A, B : TObject) : boolean of object;

Wenn ich nicht was übersehen habe, funktionieren deine Lösungen für den OP nicht, weil er Methodenzeiger speichern will, während du normale Prozedurzeiger nimmst?

(Wobei: Falls die Methoden wirklich nur immer als Self.ReadBla aufgerufen werden, könnte man das Ganze vielleicht so umformulieren, dass das Speichern normaler 4-Byte-Funktionszeiger ausreicht.)

Zitat:

Zitat von alzaimar
Delphi-Quellcode:
Var
  FunctionNames : TStringList;
  FunctionPointer : TList;

Procedure AddFunction (aName : String; aFunction : TSomeFunction);
Begin
  FunctionNames.Add(aName);
  FunctionPointer.Add(aFunction);
End;

Function GetFunction (aName : String) : TSomeFunction;
Begin
  Result := TSomeFunction(FunctionPointer[FunctionName.IndexOf(aName)]);
End;
...
AddFunction ('FooBarFunction', @FooBar);
MyResult := GetFunction('FooBarFunction')(A,B);

Dann kann man die Funktionszeiger doch auch gleich in FunctionNames.Objects stecken.

alzaimar 19. Nov 2009 14:11

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Zitat:

Zitat von Master_BB
ReadBla ist definiert als function ReadBla(AItem, BItem : Tobject) :boolean.

Zitat:

Zitat von uligerhardt
Wenn ich nicht was übersehen habe, funktionieren deine Lösungen für den OP nicht, weil er Methodenzeiger speichern will, während du normale Prozedurzeiger nimmst?

Auslegungssache. Wenn er wirklich Methodenzeiger möchte, funktioniert die QAD (Quick and Dirty) Lösung nicht. Für die OOP-Lösung muss nur die Deklaration von TSomeFunction geändert werden.
[/quote]Dann kann man die Funktionszeiger doch auch gleich in FunctionNames.Objects stecken.[/quote]
Stimmt. Ich sitze gerade mit JetLag am Nordpazifik, da passiert sowas schon mal. Das ist auch der Grund, wieso ich 'Rein/Raus' nicht kapiert habe, obwohl das sonst eigentlich recht einfach ist. :stupid:

uligerhardt 19. Nov 2009 14:30

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Zitat:

Zitat von alzaimar
Stimmt. Ich sitze gerade mit JetLag am Nordpazifik

Redmond? :-P

Master_BB 19. Nov 2009 15:00

Re: Funktionszeiger in StringList.Objects speichern und nutz
 
Nachtrag: OOP-Lösung enthält NOCH KEIN FREIGEBEN, dies muß separat geschehen.

Die OOP Lösung habe ich verwendet, wollte das ungetüm nur umgehen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:41 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