PDA

View Full Version : How to make a list of Method pointers?



chronozphere
26-04-2010, 02:42 PM
Hey guys

For my current project, I need to be able to make a list of method pointers.

Lets say I have these method types


{:: TnaEventHookProc ::}
TnaEventHookFunc = function (aEvent: Pointer): Boolean of object;
PnaEventHookFunc = ^TnaEventHookFunc;

{:: TnaUpdateProc ::}
TnaUpdateProc = procedure of object;
PnaUpdateProc = ^TnaUpdateProc;


I want to be able to store methods of these types on lists and call them all at once with the same paramters. Because these are methods (and not just functions/procedures) the variables are not just pointers. The are infact 8 bytes (contain a pointer to the procedure and one to the "Self" object).

Can anyone think of a way to make a list datastructure for this? I'm not very good with method-vars.

Thanks in advance. :)

Andreaz
26-04-2010, 02:54 PM
This is how i've done it



PMethodList = ^TMethodList;
TMethodList = Array[0..$00FFFFFF] of TMethod;

// TPHXMethodList
//------------------------------------------------------------------------------
TPHXMethodList = class
private
FCount : Integer;
FCapacity: Integer;

FList: PMethodList;

Procedure Grow;

procedure SetCapacity(const Value: Integer);
procedure SetCount (const Value: Integer);

function GetItem(Index: integer): TMethod;
procedure SetItem(Index: Integer; const AValue: TMethod);
public
constructor Create;
destructor Destroy; override;

Procedure Clear;

// Add a method to the list
procedure Add(const AMethod: TMethod);
// Remove a method from the list
procedure Remove(const AMethod: TMethod);

// Returns the index of a method in the list, -1 if not found
Function IndexOf(const AMethod: TMethod): Integer;


// Number of items in the list
Property Count : Integer read FCount write SetCount;
// The capacity of the list
Property Capacity: Integer read FCapacity write SetCapacity;
// The internal list
Property List: PMethodList read FList;
// Gets and sets items in the list
Property Items[Index: Integer]: TMethod read GetItem write SetItem; default;
end;

chronozphere
26-04-2010, 03:20 PM
Huh? Never seen such a List class. Why don't you use a dynamic array? :)

Could you show me the source of some of the methods of this class?
I'd be interested in SetCapacity, Add, IndexOf etc..

Thanks. :)

JSoftware
26-04-2010, 05:19 PM
type
TMethodList = specialize TFPGList<TMethod>;
;D

Andreaz
27-04-2010, 03:21 PM
Huh? Never seen such a List class. Why don't you use a dynamic array? :)

Could you show me the source of some of the methods of this class?
I'd be interested in SetCapacity, Add, IndexOf etc..

Thanks. :)

The implementation is basically the same as the Classes.TList implementation, just changed from Pointer to TMethod as data carrier.

Anyhow this is how it looks




constructor TPHXMethodList.Create;
begin
end;

destructor TPHXMethodList.Destroy;
begin
SetCapacity(0);

inherited Destroy;
end;

procedure TPHXMethodList.Grow;
var Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;

SetCapacity(Count + Delta);
end;

procedure TPHXMethodList.SetCapacity(const Value: Integer);
begin
if FCapacity <> Value then
begin
FCapacity := Value;

ReallocMem(FList, FCapacity * SizeOf(TMethod));
end;
end;

procedure TPHXMethodList.SetCount(const Value: Integer);
begin
FCount := Value;

if(FCount > FCapacity) then Grow;
end;

procedure TPHXMethodList.Clear;
begin
FCount:= 0;
end;

procedure TPHXMethodList.Add(const AMethod: TMethod);
begin
SetCount(Count + 1);

FList^[Count - 1].Data:= AMethod.Data;
FList^[Count - 1].Code:= AMethod.Code;
end;

procedure TPHXMethodList.Remove(const AMethod: TMethod);
var Index: integer;
begin
Index:= IndexOf(AMethod);

// The method isnt found, dont do anything more
if Index < 0 then Exit;

if Index < Count then
begin
System.Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(TMethod));
end;

Dec(FCount);
end;

function TPHXMethodList.IndexOf(const AMethod: TMethod): Integer;
var Index: integer;
begin
For Index:=0 to Count-1 do
begin
if (FList^[Index].Data = AMethod.Data) and (FList^[Index].Code = AMethod.Code) then
begin
Result:= Index;
Exit;
end;
end;
Result:= -1;
end;

function TPHXMethodList.GetItem(Index: integer): TMethod;
begin
Result:= FList^[Index];
end;

procedure TPHXMethodList.SetItem(Index: Integer; const AValue: TMethod);
begin
FList^[Index]:= AValue;
end;

chronozphere
27-04-2010, 05:11 PM
Thanks a bunch mate! :)