Skip to content

Instantly share code, notes, and snippets.

@martok
Created May 25, 2012 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martok/2789728 to your computer and use it in GitHub Desktop.
Save martok/2789728 to your computer and use it in GitHub Desktop.
TClass.ImmediateMethods
// Parses a classes vmtMethodTable and finds all `published` methods this class declares.
// Find all available functions by recusing up the hierarchy with .ClassParent
// Martok 2012 - Public Domain / CC0
TMethodTable = array of record
Code: Pointer;
Name: String;
end;
TTest = class
public
class function ImmediateMethods: TMethodTable;
end;
//...
class function TTest.ImmediateMethods: TMethodTable;
type
PVMTEntry = ^TVMTEntry;
TVMTEntry = packed record
EntrySize: Word;
Code: Pointer;
Name: ShortString;
end;
PMethodTable = ^TMethodTable;
TMethodTable = packed record
Count: Word;
Methods: array of TVMTEntry;
end;
var
pVMT: Pointer;
vmt: PMethodTable;
entry: PVMTEntry;
i: integer;
begin
SetLength(Result, 0);
// "Self" in a class method already points to the MT, so we don't strictly need that,
// but dereference the pointer anyway just to be sure the compiler did nothing weird
pVMT:= Pointer(Cardinal(Self) + vmtMethodTable);
vmt:= Pointer(PCardinal(pVMT)^);
if Assigned(vmt) then begin
SetLength(Result, vmt^.Count);
entry:= @vmt^.Methods;
for i:= 0 to vmt^.Count-1 do begin
Result[i].Code:= entry^.Code;
Result[i].Name:= entry^.Name;
Inc(Cardinal(entry), entry^.EntrySize);
end;
end;
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment