Solved

# Integer value Pointer

Posted on 2006-04-10
4,811 Views
Ok this is interesting Question.

If you have noticed every component have property "TAG" and its integer. Not many components have property pointer. For exsample every TTreeNode has propery "Data" wich is poiner its value is nil and i can use this pointer for my extensions, like adding some class or so.

So what is my idea.

pointer value is integer only in hex decimal. So for better view i will show my idea

I creare TList.

T:=TList.create;

I asign T pointer value to a pointer P

P:=T

For my component i have "TAG" propery I want to add pointer valu to "TAG" converting pointer in integer value

it should look like so

p:=\$953F10;

i:=pointertoint(p);//i know pointertoint function doesn't exist :) but that is the idea i wan't to get pointer value to integer and beck from integer value to pointer :).

commponet.tag=i;

So why i'm so interested is this kind of taging :) if component doesn't have pointer poperty i can use "tag" property like pointer to some object.

But i need these to function:

pointertoint(p:pointer):integer;
inttopointer(i:integer):pointer;

I think this idea is nice i will continue to solve this interesting idea my self but fieel free to try to solve it first.
0
Question by:Kristao

LVL 26

Accepted Solution

Because pointer and integer are both 4 byte data types, a simple cast can be used.

var i: Integer;
p: Pointer;
begin

i:=Integer(p); // Cast pointer to int
p:=Pointer(i); // Cast int to pointer

end;

--

Regards,
Russell

0

LVL 5

Expert Comment

Yep, Russel is spot on ...

-----------------------------

TComponent.Tag

Stores an integer value as part of a component.

property Tag: Longint;

Description

Tag has no predefined meaning. The Tag property is provided for the convenience of developers. It can be used for storing an additional integer value or it can be typecast to any 32-bit value such as a component reference or a pointer.

0

LVL 3

Expert Comment

You can freely type cast any 32-bit variable (or less) to another 32-bit type.
32 bit type in Delphi are: pointer, integer, cardinal, single.

So if you want to 'save' a pointer value to the 'tag' property you can do that:

Button1.Tag := Integer(Button2);

which.. later on, you can do this:

TButton(Button1.Tag).Click;

Or.... the other way around, you can create a list of integer values using TList:

var I: Integer;
MyList.Add(TObject(I)); // type cast integer to pointer type

... and retrieve it again:

I := Integer(MyList.Items[0]);

Note that the compiler will give you warning of unsafe typecasting, you'll need
to be very carefull with this method.

regards,
Ferry
0

LVL 3

Expert Comment

Or... of course you can create your 2 conversions functions:

function PointerToInt(APointer: Pointer): Integer;
begin
Result := Integer(APointer);
end;

function IntToPointer(AInt: Integer): Pointer;
begin
Result := Pointer(AInt);
end;

0

LVL 17

Expert Comment

here's a working example from 1 of my projects

type TPositionObject = class
public
startx, starty: integer;
end;

panel2.Tag := Integer(TPositionObject.Create);

procedure TForm1.Panel_MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
TPositionObject( (Sender AS TPanel).Tag).startx := X;
TPositionObject( (Sender AS TPanel).Tag).starty := Y;
TPositionObject( (Sender AS TPanel).Tag).Moving := True;
end;

0

LVL 7

Expert Comment

Keep in mind that Pointer and Longint while in 32 bit windows are the same size.  That is not guaranteed in 64 bit windows.  Not sure how Delphi and Borland will/ or do handle this in 64 bit.
0

LVL 5

Expert Comment

Also keep in mind that -some- exisiting 3rd party component sets use this for there own purposes, commonly, internationalisation and skinning components, for instance.
0

LVL 1

Expert Comment

I created this little experiment to see what will happen.  I learned something today.

procedure TForm1.Button1Click(Sender: TObject);
var
_pointers : TList;
x, iTestP, iTestV ,i: integer;
lb, lsTest : TListBox;
begin
x := 5;
lb := ListBox1; // A listbox on my form

_pointers := TList.Create;
//You need to add the @ before type variables to get a pointer to that value.

lsTest := TListBox(_pointers.Items[1]);//Retreive listbox pointer from IList
iTestP := integer(_pointers.Items[0]);//This returns a pointer to integer value
iTestV := integer(_pointers.Items[0]^);//Returns the value of the integer

//iTestP is a pointer to my origional value.  You can also retreive that
//value by
iTestV := integer(pointer(iTestP)^);

//This means you can store the pointer (iTestP) in the tag element, and
//later on retreive the value like just above.

ShowMessage('Pointer to origional value ' + IntToStr(iTestP));
ShowMessage('Origional value ' + IntToStr(iTestV));

for i := 0 to lsTest.Items.Count-1 do begin
ShowMessage(lsTest.Items[i]);
end;
end;
0

LVL 7

Expert Comment

ruanlab123 just for clarification in case someone reading your post doesn't understand it.
------------------

you declared your x,iTestP,iTestv as Integers in the local context and got the address to those pointers with the @ operator.  These pointers are not valid outside this proc's scope.

x :PInteger;  or X: ^Integer;  (same thing).

now x is a true pointer type.

New(X) will get the memory for an Integer and X will POINT to that memory (or in English the value of X is the @ of the memory returned from the New function).

While the pointer X is local to the scope of your function.  The memory that X POINTS to is not.  So if you add x to a TList that is global to an object then it can be accessed by any code that has access to the object.  ex.  Tlist.Get accesses a list of pointers that are global to the TList object.

When you wish to access the value that X points to you use the^.

ex.
var
MyInt : Integer
begin
MyInt := X^;  not X;
end;

also You obtained the memory with the NEW function.  It is your responsibility to release it with the DISPOSE function.
Dispose(X);

------------
Cheers;

0