4

I Need to access a strict private class var value of a class using his instance and a offset to the variable.

so far tried this , check this sample class

type
  TFoo=class
   strict private class var Foo: Integer;
   public
   constructor Create;
  end;

constructor TFoo.Create;
begin
  inherited;
  Foo:=666;
end;

//this function works only if I declare the foo var as 
//strict private var Foo: Integer;
function GetFooValue(const AClass: TFoo): Integer;
begin
  Result := PInteger(PByte(AClass) + 4)^
end;

As you see the function GetFooValue works only when the foo variable is not declarated like a class var.

The question is how I must modify the GetFooValue in order to get the value of Foo when is declarated like strict private class var Foo: Integer;

LU RD
  • 34,438
  • 5
  • 88
  • 296
Salvador
  • 16,132
  • 33
  • 143
  • 245
  • Just some random guesses: Have you tried this without the `+ 4`? And what happens, if you create an object of type `TFoo` (that is, if you "use the class"), before calling GetFooValue? – kol Dec 18 '11 at 21:22
  • Presumably you don't have the source code available? Is that right? – David Heffernan Dec 18 '11 at 21:58
  • @DavidHeffernan, Yes that is right, I only had the declarations of the class. and the dcu files. – Salvador Dec 18 '11 at 22:00
  • I can gain access to all strict private members of the target class using a pointer (to the instance) and a offset to the field or property, except the declarated like `class var`. – Salvador Dec 18 '11 at 22:06
  • 3
    If you've got no source then you're out of luck. Class vars aren't fields, they're global variables, so you can't get at them with field-structure hacks. This is another reason why you should never use libraries you have no source to. – Mason Wheeler Dec 18 '11 at 22:08

2 Answers2

7

To access a strict private class var, Class Helper to rescue.

Example :

type
  TFoo = class
  strict private class var
    Foo : Integer;
  end;

  TFooHelper = class helper for TFoo
  private
    function GetFooValue : Integer;
  public
    property FooValue : Integer read GetFooValue;
  end;

function TFooHelper.GetFooValue : Integer;
begin
  Result:= Self.Foo;  // Access the org class with Self
end;

function GetFooValue( F : TFoo) : Integer;
begin
  Result:= F.GetFooValue;
end;

Var f : TFoo;//don't need to instantiate since we only access class methods

begin
  WriteLn(GetFooValue(f));
  ReadLn;
end.

Updated example to fit the question.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
LU RD
  • 34,438
  • 5
  • 88
  • 296
  • I also answered a previous question of yours [accesing-a-strict-private-field-using-the-rtti](http://stackoverflow.com/questions/7525071/accesing-a-strict-private-field-using-the-rtti/8556030#8556030), using class helpers. – LU RD Dec 19 '11 at 00:40
2

You really can't do it that way. A class var is implemented as a global variable, and its memory location doesn't have any predictable relationship to the location of the class VMT (what the class reference points to), which is located in the constant data region of your process's memory.

If you need access to this variable from outside the class, declare a class property that references it as its backing field.

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477