views:

176

answers:

2

I need to get pointer to my class instance inside this instance. I can't use "Self" directly, I need store pointer for future usage. I tried next code:

type
    TTest = class(TObject)
    public
        class function getClassPointer: Pointer;
        function getSelfPointer: Pointer;
    end;

class function TTest.getClassPointer: Pointer;
begin
    Result := Pointer(Self);
end;

function TTest.getSelfPointer: Pointer;
begin
    Result := Pointer(Self);
end;

And both result are wrong - this code:

test := TTest.Create;
Writeln('Actual object address: ', IntToHex(Integer(@test), 8));
Writeln('Class "Self" value: ', IntToHex(Integer(test.getClassPointer()), 8));
Writeln('Object "Self" value: ', IntToHex(Integer(test.getSelfPointer()), 8));

returns:

Actual object address:    00416E6C
Class "Self" value:       0040E55C
Object "Self" value:      01EE0D10

Please, help me understand, what is this "Self" value ? Is "Self" a pointer to this class instance ? How use this pointer to future use outside of this object ? How get proper pointer from this value ?

A: 

In your code fragment test already is a reference to the real instance, so you should try

Writeln('Actual object address: ', IntToHex(Integer(Pointer(test)), 8));

And you probably don't need any getSelfPointer method. If you want a second reference to the object instance that test already references, write:

var
  SecondReferenceToTest: TTest;
SecondReferenceToTest := test;

To see this, try something like:

type
  TTest = class(TObject)
  public
    Name: string;
  end;

procedure TestProc;
var
  test, SecondReferenceToTest: TTest;
begin
  test := TTest.Create;
  try
    test.Name := 'Named via "test" reference';
    SecondReferenceToTest := test;
    ShowMessage(SecondReferenceToTest.Name);
  finally
    test.Free;
  end;
end;
Ulrich Gerhardt
This way - to get reference outside of object, but what I must do, to return valid pointer from within this object's method ? Like in my sample.
soar
@Soara, if you're going to call a method on the object, then you *already have* a reference to the object. The object itself doesn't have any "special" access to it. Within an instance method `Self` is a reference to the object, the same reference that callers must already have if they're calling methods on the object. Within a class method, `Self` is a reference to the class, not any instance of the class.
Rob Kennedy
My question - is only sample, really I use structure, where object placed in other object as field, and there is not "test" within it. Now I can pass to it proper pointer. Thanks to all !
soar
I still have the feeling that you are something the wrong way...
Leonardo Herrera
+10  A: 

You're trying to compare three completely different entities.

@test returns the address of the variable test, not the object instance that it points to.

test.getClassPointer() returns the address of the class metadata, a constant data structure generated by the compiler where the runtime can find the virtual method table, runtime type info tables, and more. All instances of a class share the same class metadata structure. The pointer to the class metadata is the object instance's type identity - it's how the object knows what type it is at runtime.

test.getSelfPointer() gives you the actual address of the object instance in memory. Two object instances (created separately) will have different instance addresses. test.getSelfPointer() will be equal to the contents of the test instance variable: Pointer(test)

For example (pseudocode, not tested):

type TTest = class
     end;

var test1: TTest;
    test2: TTest;

begin
  test1 = TTest.Create;  // allocates memory from the global heap, stores pointer
  test2 = test1;         // copies the pointer to the object into test2 variable
  writeln("Test1 variable points to: ", IntToHex(Integer(Pointer(test1))));
  writeln("Test2 variable points to: ", IntToHex(Integer(Pointer(test1))));
end.
dthorpe
Thank's ! Now I understand how to use this !TTest(Pointer(test)) or TTest(test.getSelfPointer()) - is what i need =)
soar
These are very strange constructs for Delphi. Are you sure you're not making things overly complicated for yourself? your foo = TTest(Pointer(test)) is the same as just saying foo = test. Every object instance variable in Delphi is actually a pointer. The pointerness is just beneath the surface.
dthorpe
Furthermore, `getClassPointer` is the same as the built-in `ClassType` method.
Rob Kennedy
My question - is only sample, really I use structure, where object placed in other object as field, and there is not "test" within it. Now I can pass to it proper pointer. Thanks to all !
soar