[Delphi] toegang tot private methods van een class

Pagina: 1
Acties:

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 12:54

Tomatoman

Fulltime prutser

Topicstarter
Ik ben bezig een procedure te schrijven die een paar private methods van TDecisionGrid moet benaderen:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type
  TGridHack = class(TDecisionGrid)
  end;

{ DoeIets is een gewone procedure, GEEN method van TGridHack! }
procedure DoeIets(Component: TComponent; ACol: ARow: Integer);
var
  ACol, ARow: Integer;
  Grid: TGridHack;
begin
  { Component is altijd een instantie van TDecisionGrid, nooit van 
    TGridHack. }
  Grid := Component as TGridHack; 
  with Grid do
  begin
    if (RowHeights[ARow] <= 0) or (ColWidths[ACol] <= 0) then
      ...

RowHeights en ColWidths zijn protected methods van TDecisionGrid - zij kunnen via de omweg van TGridHack worden benaderd >:). Nu wil ook ik een paar private methods van TDecisionGrid benaderen. Is dit via een truc mogelijk?

[ Voor 0% gewijzigd door Tomatoman op 16-10-2002 01:07 . Reden: code vereenvoudigd ]

Een goede grap mag vrienden kosten.


Verwijderd

Je kunt bij de private fields van een object; dus als je de private methods kopieert ben je er denk ik.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Het korte antwoord is: Nee, dat kan niet. Die 'hack' die waar je het hier over hebt werkt alleen voor de protected members.

Het iets langere antwoord is: Ja, het kan in speciale gevallen. In C++ kan je andere klassen als friend aanmerken zodat zij er wel bij kunnen. Delphi kent dit ook, maar het is minder flexibel. In Delphi is elke klasse friend van de ander als ze in de zelfde unit zitten. Daar heb ik in het geval van een TDecisionGrid waarschijnlijk weinig aan.

We adore chaos because we like to restore order - M.C. Escher


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Eigenlijk is het geheim ;) maar ik vertel het nu toch maar. Als je echt wanhopig bent is er toch nog een weg om bij de private members te komen, maar dit is dan ook wel een echte eersteklas hack :p

Hack classes for private members

Getting access to the protected section is one thing, but what about the private section? Well, it seems that you can also accomplish this, although in a much less resilient fashion than might be desired.

It relies on you knowing how many data fields precede your target private data field, and how many bytes they take up. You add this to the instance size of the ancestor class, and that gives the offset from the start of the object's instance data at which the field lies.

Assuming you have the source for the original class, this is just tedious, but of course you need to re-check everything as you move from product version to product version.

Listing 28 shows a function that takes three parameters. The first is an object reference for the object whose private data field you want. The second is a class reference to the class that defines the private data field (which might be one of your object's ancestor types). The last parameter is the byte offset that the private data field resides at, in terms of the class that defines it.

Listing 28: A function that will access private members
code:
1
2
3
4
5
6
7
8
9
function GetPrivateField(Obj: TObject;
  Cls: TClass; DataOffset: Cardinal): Pointer;
var
  ParentInstanceSize: Cardinal;
begin
  //Get parent instance data size and add on the VMT pointer
  ParentInstanceSize := Cls.ClassParent.InstanceSize + 4;
  Result := Pointer( Cardinal( Obj ) + ParentInstanceSize + DataOffset )
end;

As a massively academic example, consider the ActiveControl property of a form. This property surfaces the private FActiveControl object reference data field, defined to be of type TWinControl. If we forget about the property being available, we can concentrate on trying to read this private data field directly.

TCustomForm defines the FActiveControl data field as the first field (offset 0). To access this field, you can use this call.
code:
1
2
3
4
var
  Ctl: TWinControl;
...
Ctl := TWinControl( GetPrivateField( Self, TCustomForm, 0 )^ );

We adore chaos because we like to restore order - M.C. Escher


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 30-08 09:55

Creepy

Tactical Espionage Splatterer

zo dan.. DAT noem ik nou een vieze hack ;)

[moraalridder]
Is het niet mogelijk om op een andere manier de TDicisionGrid te benaderen/over te erven/whatever om toch te doen wat je wilt? Het word er nou niet echt netter p[
[/moraalridder] ;)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney