Recent

Author Topic: Is there a function/operator in FPC that returns the offset of a field ?  (Read 11488 times)

jamie

  • Hero Member
  • *****
  • Posts: 7776
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #15 on: November 13, 2018, 11:47:51 pm »
Ok, so create a writeable constant of your record and then reference it the same way but subtract the desired field from the
base of the constant and you have your offset..

 But I think you would rather have the compiler just give you a number is my guess or you are just being cantankerous.


The only true wisdom is knowing you know nothing

440bx

  • Hero Member
  • *****
  • Posts: 6542
Re: Is there a function/operator in FPC that returns the offset of a field ?
« Reply #16 on: November 13, 2018, 11:55:05 pm »
Ok, so create a writeable constant of your record and then reference it the same way but subtract the desired field from the
base of the constant and you have your offset..

 But I think you would rather have the compiler just give you a number is my guess or you are just being cantankerous.
No, I am not being cantankerous. <chuckle>.  Yes, I would much rather have the compiler tell me the offset because it already has it in its symbol table(s), just like high and low for an array. The compiler has the information and, that information is often useful to declare other types that adjust automatically to changes in the types they depend on (as for loop index ranges change if they are coded using high and low, for instance.)
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

kupferstecher

  • Hero Member
  • *****
  • Posts: 622
The following expression might look strange, but we consider it one of the official ways to retrieve the offset to a field ;)

Code: Pascal  [Select][+][-]
  1. PrnUInt(@TSomeRecord(Nil^).ThirdField)

The same I tried for a class and it works if the dereferencing of Nil is removed (as a class carries the address):

Code: Pascal  [Select][+][-]
  1. PrnUInt(@TSomeClass(Nil).ThirdField)

Is this considered save as well?

Thaddy

  • Hero Member
  • *****
  • Posts: 19276
  • Glad to be alive.
Is this considered save as well?
The address value is safe as in: the compiler gives you that address and it is the correct address.
But the compiler can in no way verify what you do with that address:
A Pointer has no type information, a pointer is opaque, just a value.

How can that be "safe" in the general sense?
objects are fine constructs. You can even initialize them with constructors.

kupferstecher

  • Hero Member
  • *****
  • Posts: 622
But the compiler can in no way verify what you do with that address:
A Pointer has no type information, a pointer is opaque, just a value.

How can that be "safe" in the general sense?
Yes, its true. And I also hesitate to use it. The usecase I have is in a Python4Delphi callback function, the instances of the class do not exist yet, so only the offset of the methods/variables is defined and in the callback function combined with the instance to directly call the method/value. But as the offset has to be given at initialisation (user code), it's probably not a good idea.

jamie

  • Hero Member
  • *****
  • Posts: 7776
This is where it gets shady and why things like DLL's make this easy, they have an address table that always gets updated whenever you rebuild the DLL so all you need to do is reference the item of interest via a name entry of the DLL.

 I suppose you could do the same using Interfaces, too!

Jamie
The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 19276
  • Glad to be alive.

Yes, its true. And I also hesitate to use it. The usecase I have is in a Python4Delphi callback function, the instances of the class do not exist yet, so only the offset of the methods/variables is defined and in the callback function combined with the instance to directly call the method/value. But as the offset has to be given at initialisation (user code), it's probably not a good idea.
In the case of python4delphi I'd still consider it if it is really just the offset and not the start address. Note that for field access of records, don't forget {$packrecords(c)} which is what the python API expects.
« Last Edit: April 02, 2026, 06:52:05 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

kupferstecher

  • Hero Member
  • *****
  • Posts: 622
[...] so all you need to do is reference the item of interest via a name entry of the DLL.

I suppose you could do the same using Interfaces, too!

How do you mean that? Working with names instead of pointers/addresses?

In the case of python4delphi I'd still consider it if it is really just the offset and not the start address.
Yes it's just the offset. But putting in a wrong address might crash the program.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6398
  • Compiler Developer
The following expression might look strange, but we consider it one of the official ways to retrieve the offset to a field ;)

Code: Pascal  [Select][+][-]
  1. PrnUInt(@TSomeRecord(Nil^).ThirdField)

The same I tried for a class and it works if the dereferencing of Nil is removed (as a class carries the address):

Code: Pascal  [Select][+][-]
  1. PrnUInt(@TSomeClass(Nil).ThirdField)

Is this considered save as well?

Hadn't seen it use for classes, but I don't see why it shouldn't be safe. It will also work correctly should the compiler decide to reorder fields if -O4 is used.

kupferstecher

  • Hero Member
  • *****
  • Posts: 622
It will also work correctly should the compiler decide to reorder fields if -O4 is used.
Good to know, thanks!

 

TinyPortal © 2005-2018