Reputation: 75
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 ?
Upvotes: 7
Views: 7169
Reputation: 36082
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.
Upvotes: 14
Reputation: 14001
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;
Upvotes: 0