Recent

Author Topic: Question: how to type-cast a general pointer to a PtrUInt variable ?  (Read 19423 times)

KlausGunther

  • New Member
  • *
  • Posts: 36
I'm replacing all my integer variables holding 32 bit pointers to PtrUInt data type. But the compiler warnes me at each and every occurence. What would be the correct type-casting ?

I found a working trick for PString types (adresses of strings). I do the following:
Code: [Select]
var
a64: PtrUint;
s: string;
begin
s := 'this is my text';
a64 := WParam(s);
end
No compiler warnings, and works fine in 32 bit environment. 64 bit environment will soon be checked out. But it seems a bit arkward, isn't it ? Is there a more straight-forward method, working with all types of pointers ?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11453
  • FPC developer.
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #1 on: December 30, 2012, 12:52:23 am »
This code is probably horribly wrong.  "s" is a managed type whose contents will be killed after the "end" and then a64 will point into nowhere.

KlausGunther

  • New Member
  • *
  • Posts: 36
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #2 on: December 30, 2012, 01:07:23 am »
Oh yes, shure ! I just tried to produce a complete code. The important thing is just:
Code: [Select]
a64 := WParam(s);making shure that a64 receives a valid PtrUInt value without compiler hints or warnings about non-portable conversions. The value seems correct, and the compiler doesn't say anything. This line would be used throughout the whole package, if there isn't a more elegant way to cast a string pointer to a PtrUInt.

And what about general pointer types ? How to cast them to PtrUInt correctly ?

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #3 on: December 30, 2012, 09:46:50 am »
Commonly string with pointers is referred to as PChar. When you assign string to PChar, it copies the memory, if i recall.

KlausGunther

  • New Member
  • *
  • Posts: 36
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #4 on: December 30, 2012, 10:58:19 am »
So, do you think that
Code: [Select]
a64 := WParam(s);creates a copy of the string s and places the address of that copy into a64 ?

What would be the correct way to implement the Lazarus version of the Delphi code
Code: [Select]
a64 := @s;in Lazarus/FPC without having the compiler mock me ?

EDIT

And similar problem: I have to cast a procedure address as LongInt, as in Delphi code
Code: [Select]
  Result := CallWindowProc(Pointer(HotKey_oldmsgproc), wnd, Msg, wParam, lParam); or in Delphi code
Code: [Select]
  SetWindowLong(wnd, GWL_WNDPROC, Integer(@HotKey_MsgProc));I just can't find a way to avoid the hint: Conversion between ordinals and pointers is not portable.

How can I cast those adresses to a PtrUInt ?
« Last Edit: December 30, 2012, 05:16:09 pm by KlausGunther »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11453
  • FPC developer.
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #5 on: December 30, 2012, 05:12:09 pm »
There is no correct and 100% safe way to do that, since at any point the compiler might change the location of the string's allocation.

That's why they are called dynamic.

If you need to store character data for a long time in a pointer, allocate memory to a pchar and use that.

KlausGunther

  • New Member
  • *
  • Posts: 36
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #6 on: December 30, 2012, 05:18:04 pm »
Yes, I know that. It's not for a long storage, but just for building the right parameter type for a function call. So I need to cast adresses to PtrUInt. Be it adresses of variables, string, procedures - it's all for the same usage.

KlausGunther

  • New Member
  • *
  • Posts: 36
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #7 on: December 30, 2012, 06:33:53 pm »
I found a trick to cast pointers to a PtrUInt:
Code: [Select]

var
  p: pointer;
  adr: PtrUInt;
begin
      adr := 0;                                    // initialize variable to avoid compiler hint
      p := @HotKey_MsgProc;            // get a procedure pointer (or any other pointer or address)
      move(p,adr,sizeof(adr));            // cast to PtrUint by brutal copy
   // and now, use the pointer value where a LongInt is expected
      SetWindowLong(wnd, GWL_WNDPROC, adr);
 
Again, it's not a complete program, just a sample code with the variable declarations.

It's working. But I find it really nasty. Isn't there a type-cast to load a pointer into a PtrUInt ? The latter isn't it designed for holding pointers ? But how do I get them into it ?

EDIT

I found the symetric method to cast an integer variable holding a pointer to a pointer variable:
Code: [Select]
        var
          p: pointer
        begin
          p := nil;
          move(HotKey_oldmsgproc,p,sizeof(p));
          Result := CallWindowProc(p, wnd, Msg, wParam, lParam);   

All this avoids compiler hints ans warning, and it's working. But ugly. There should be an in-built way to accomplish these casts !
« Last Edit: December 30, 2012, 06:47:05 pm by KlausGunther »

Laksen

  • Hero Member
  • *****
  • Posts: 745
    • J-Software
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #8 on: December 30, 2012, 06:39:06 pm »
Code: [Select]
var p: pointer;
    pt: PtrUInt;
begin
   p := @something;
   pt := PtrUInt(p);
end;

This will always work

KlausGunther

  • New Member
  • *
  • Posts: 36
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #9 on: December 30, 2012, 07:05:56 pm »
It works, certainly. But the compiler doesn't like it: it warns about non-portable conversion between ordinals and pointers, at the line
Code: [Select]
   pt := PtrUInt(p);That's exactly what I want to avoide. Otherwise, I'll have hundreds of hints or warnings, and il will be really hard to find those which are really important. Because during conversion, this hint is usefull to show the points which need special attention. So, I don't want to block these hints. I just want to find a regular solution fully accepted by the compiler.

KlausGunther

  • New Member
  • *
  • Posts: 36
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #10 on: January 07, 2013, 11:11:45 am »
Isn't there really no "regular" way to cast a pointer or an address to a PtrUInt variable ? I'm using MOVE and it's working, but I don't feel happy with this work-arround. I have to do:
Code: [Select]
var
adr1,adr2: PtrUInt;
p: pointer;
s: string;
...
adr 1:= p;
adr2 := @s;
 

There are compiler warnings (conversion is not portable). Actually, I'm doing this:
Code: [Select]
move(p,adr1,sizeof(adr1));
p := @s;
move(p,adr2,sizeof(adr2));

No more warnings, but no more control, too. There is certainly a way to do such casts without the compiler mocking about that.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9874
  • Debugger - SynEdit - and more
    • wiki
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #11 on: January 07, 2013, 12:17:14 pm »
In the Lazarus IDE you can write {%H-}

  i:={%H-}PtrUInt(p);

The IDE will filter the message (if it is a hint).

As for your question.

Yes PtrUInt has exactly the purpose of holding a pointer.
But look up its declaration. It is simply a DWord or QWord or similar. There is an IFDEF and it is aliased to the correct size type.

So for the compiler it is still casting a pointer (of which the compiler knows, that it has different sizes on different platforms) to an integer type (that the compiler believes to be of the same size always (might be ($mode) dependent)).
There is no entirely "magic" integer type, for which the compiler knows it is save for pointers.

You can write the typecast as an inline function. Then it is in a single place only.

KlausGunther

  • New Member
  • *
  • Posts: 36
Re: Question: how to type-cast a general pointer to a PtrUInt variable ?
« Reply #12 on: January 07, 2013, 05:32:07 pm »
YES ! That's it !

I dit this:
Code: [Select]
function PtrToI64(p:pointer):PtrUInt; inline;
begin
  result := {%H-}PtrUInt(p);
end;
and I call it like this:
Code: [Select]

var
  p: pointer;
  adr: PtrUInt;
...
p := @MyString;
adr := PtrToI64(p);

Works fine and no more warnigs. Exactely what I wanted. Thank you very much !

 

TinyPortal © 2005-2018