Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi Self-Pointer usage

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 ?

like image 676
soar Avatar asked Sep 29 '10 17:09

soar


1 Answers

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.
like image 95
dthorpe Avatar answered Sep 24 '22 19:09

dthorpe