Recent

Author Topic: Questions about GUID declarations magic  (Read 2652 times)

440bx

  • Hero Member
  • *****
  • Posts: 6063
Questions about GUID declarations magic
« on: July 09, 2025, 12:47:52 pm »
Hello,

It looks like declaring GUIDs follow a different set of rules than declaring any other record type. 

Consider the following code:
Code: Pascal  [Select][+][-]
  1.  
  2. {$define USE_DATA_TYPE_IDENTICAL_TO_GUID}
  3.  
  4. program _GUID_Declarations;
  5.  
  6. uses
  7.   Windows,
  8.   ActiveX
  9.   ;
  10.  
  11.  
  12. type
  13.   { EXACT copy of TGUID definition                                            }
  14.  
  15.   TDATA_TYPE = packed record
  16.      case integer of
  17.         1 : (
  18.              Data1 : DWord;
  19.              Data2 : word;
  20.              Data3 : word;
  21.              Data4 : array[0..7] of byte;
  22.             );
  23.         2 : (
  24.              D1 : DWord;
  25.              D2 : word;
  26.              D3 : word;
  27.              D4 : array[0..7] of byte;
  28.             );
  29.         3 : ( { uuid fields according to RFC4122 }
  30.              time_low : dword;                  // The low field of the timestamp
  31.              time_mid : word;                      // The middle field of the timestamp
  32.              time_hi_and_version : word;           // The high field of the timestamp multiplexed with the version number
  33.              clock_seq_hi_and_reserved : byte;     // The high field of the clock sequence multiplexed with the variant
  34.              clock_seq_low : byte;                 // The low field of the clock sequence
  35.              node : array[0..5] of byte;           // The spatially unique node identifier
  36.             );
  37.   end;
  38.  
  39. type
  40.   TDATA_TYPE2 = TGUID;
  41.  
  42.  
  43. const
  44.   { this compiles                                                             }
  45.  
  46.   SOMEGUID  : TGUID        = '{00000114-0000-0000-C000-000000000046}';
  47.  
  48. const
  49.   { this also compiles                                                        }
  50.  
  51.   SOMEGUID2 : TDATA_TYPE2  = '{00000114-0000-0000-C000-000000000046}';
  52.  
  53.  
  54. {$ifdef USE_DATA_TYPE_IDENTICAL_TO_GUID}
  55. const
  56.   { this does NOT compile ... why ??? - TDATA_TYPE is identical to TGUID      }
  57.  
  58.   SOMEGUID2 : TDATA_TYPE = '{00000114-0000-0000-C000-000000000046}';
  59. {$endif}
  60.  
  61.  
  62. // in activex.pp
  63. //
  64. // IID_IOleWindow : TGUID = '{00000114-0000-0000-C000-000000000046}';
  65. //
  66. // IOleWindow = interface(IUnknown)
  67. //    ['{00000114-0000-0000-C000-000000000046}']      { <- duplicated value   }
  68. //
  69. //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  70. //
  71. //    this duplicated value opens the door to errors
  72.  
  73.  
  74. const
  75.   { define IID as plain - untyped - constant                                  }
  76.  
  77.   IID_IOleWindow = '{00000114-0000-0000-C000-000000000046}';
  78.  
  79. type
  80.   { _IOleWindow                                                               }
  81.  
  82.   IOleWindow = interface(IUnknown) [IID_IOleWindow]  { <- use the plain constant }
  83.  
  84.  
  85.     { methods here }
  86.  
  87.   end;
  88.  
  89. begin
  90.  
  91.   readln;
  92. end.                          
  93.  
On line 15, there is an EXACT copy of the definition of TGUID (copy/pasted.) if I try to declare a value using the copy of TGUID's definition (line 58), the compiler rejects it, that's in spite of the fact that other than the data type name being different, the definition is identical to the one in lines 46 and 51 which are both accepted.



Now a different question altogether....

In activex.pp, just about every interface id is declared as a typed constant (line 64) and then restated in full in the interface declaration (line 67.)  The concern here is possible errors due to incorrect duplication of the interface id.

The compiler accepts declaring the constants without type (which as a bonus saves data storage) (line 77) and use that constant as the interface id in the interface declaration (line 82)

There are several advantages to that method, one is that no storage in the data section is necessary, it is impossible to modify the interface id since it is not stored and lastly, there is no interface id duplication.

My only concern is, does doing the way shown in lines 77 and 82 have the potential to cause problems that the other way does not ?

Thank you for your help.

Attached to the post is the code presented above.  Comment/uncomment the define to see the different behavior.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 18726
  • To Europe: simply sell USA bonds: dollar collapses
Re: Questions about GUID declarations magic
« Reply #1 on: July 09, 2025, 01:00:08 pm »
GUIDs are indeed parsed differently for COM, otherwise you won't come away with its string representation in the code. It makes it a special kind of record. I am not sure if CORBA interfaces are parsed differently, though:
Many people use GUIDS for CORBA interfaces (allowed) but there the GUID is a direct string representation and not really a GUID in the COM sense. CORBA just needs a string identifier and you can misuse a guid for that. In CORBA, for whatever the reason, you can replace the GUID by 'Elephant' or something.
And a string is NOT a GUID for COM.
In COM a GUID is a binary format whereas in CORBA it is interpreted as a string.
So, given that, a COM GUID needs to be parsed differently.
(Even if you use a variant record).
IOW the compiler needs to resolve the binary signature for COM but not for CORBA where it is a string.
« Last Edit: July 09, 2025, 01:10:18 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12630
  • FPC developer.
Re: Questions about GUID declarations magic
« Reply #2 on: July 09, 2025, 01:09:48 pm »
I think the problem is that TGUIDs can't be true constants because they are too large.

I'm not sure how much identity Corba actually supports.

Thaddy

  • Hero Member
  • *****
  • Posts: 18726
  • To Europe: simply sell USA bonds: dollar collapses
Re: Questions about GUID declarations magic
« Reply #3 on: July 09, 2025, 01:12:11 pm »
I think the problem is that TGUIDs can't be true constants because they are too large.

I'm not sure how much identity Corba actually supports.
They can be if you followed my advice and patch activex.pp to compile the typed constants in {$J-} state.
Then they end up in rodata and are by definition immutable.
Maybe you did not read that thread yet? It contains a patch.
I respect that you can not read everything and can reprovide the patch again.
« Last Edit: July 09, 2025, 01:13:53 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12630
  • FPC developer.
Re: Questions about GUID declarations magic
« Reply #4 on: July 09, 2025, 01:13:49 pm »
I'm not really interested in Corba, but what thread exactly ? There is no in your post.

Thaddy

  • Hero Member
  • *****
  • Posts: 18726
  • To Europe: simply sell USA bonds: dollar collapses
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12630
  • FPC developer.
Re: Questions about GUID declarations magic
« Reply #6 on: July 09, 2025, 01:53:25 pm »
Ah you meant that, that prohibits writing, and might change the segment on systems.

The matter is if that makes it for the compiler any easier to reference it (it is still a typed constant construct, and a structured one even). But that is outside of my direct experience, someone more knowledgeable with compiler internals must comment on that.

The constants are however TGUID typed for a reason, to use in queryinterface and other functions, so redefining them as string is not really helpful.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: Questions about GUID declarations magic
« Reply #7 on: July 09, 2025, 02:18:30 pm »
The constants are however TGUID typed for a reason, to use in queryinterface and other functions, so redefining them as string is not really helpful.
That's the crux of the matter.  The compiler does some "magic" parsing for GUIDs when the GUID is declared but, that's the only time it does that "custom" GUID parsing.  Any other time it treats the constant as a string, not a guid.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 18726
  • To Europe: simply sell USA bonds: dollar collapses
Re: Questions about GUID declarations magic
« Reply #8 on: July 09, 2025, 03:24:47 pm »
Not quite correct: the GUID in COM is binary and can't be used as a string.
You can use it as such in QueryInterface, but internally that also gets a binary representation.
« Last Edit: July 09, 2025, 04:32:04 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Thaddy

  • Hero Member
  • *****
  • Posts: 18726
  • To Europe: simply sell USA bonds: dollar collapses
Re: Questions about GUID declarations magic
« Reply #9 on: July 09, 2025, 04:26:32 pm »
@Marcov
I filed report + patch #41325
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Thaddy

  • Hero Member
  • *****
  • Posts: 18726
  • To Europe: simply sell USA bonds: dollar collapses
Re: Questions about GUID declarations magic
« Reply #10 on: July 09, 2025, 04:28:09 pm »
The constants are however TGUID typed for a reason, to use in queryinterface and other functions, so redefining them as string is not really helpful.
I never suggested that. I merely pointed out how COM and CORBA handle GUIDS differently. Only for the latter it is just a string, any string. People tend to forget or not understand that. Rather common.
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

ASerge

  • Hero Member
  • *****
  • Posts: 2475
Re: Questions about GUID declarations magic
« Reply #11 on: July 09, 2025, 08:46:33 pm »
The compiler does some "magic" parsing for GUIDs when the GUID is declared but, that's the only time it does that "custom" GUID parsing. 
This is documented in Interface identification: A GUID:
Quote
A constant of type TGUID can be specified using a string literal

Thaddy

  • Hero Member
  • *****
  • Posts: 18726
  • To Europe: simply sell USA bonds: dollar collapses
Re: Questions about GUID declarations magic
« Reply #12 on: July 09, 2025, 08:54:57 pm »
Yes, but in the case of COM that is syntax, not how the GUID is interpreted.
Or is that what you mean? A COM GUID is binary and the compiler takes care of that.

I agree that the documentation could be much more clear.
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: Questions about GUID declarations magic
« Reply #13 on: July 09, 2025, 10:39:25 pm »
This is documented in Interface identification: A GUID:
Quote
A constant of type TGUID can be specified using a string literal
Somehow I missed that when reading the documentation (or maybe simply didn't remember it.)  Thank you for pointing that out, I'll re-read that part of the documentation.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6306
  • Compiler Developer
Re: Questions about GUID declarations magic
« Reply #14 on: July 09, 2025, 11:10:00 pm »
It looks like declaring GUIDs follow a different set of rules than declaring any other record type. 

snip

On line 15, there is an EXACT copy of the definition of TGUID (copy/pasted.) if I try to declare a value using the copy of TGUID's definition (line 58), the compiler rejects it, that's in spite of the fact that other than the data type name being different, the definition is identical to the one in lines 46 and 51 which are both accepted.

The compiler explicitly checks for System.TGUID, just like it looks for System.TObject (and other non-primitive types declared in the System unit).

There are several advantages to that method, one is that no storage in the data section is necessary, it is impossible to modify the interface id since it is not stored and lastly, there is no interface id duplication.

My only concern is, does doing the way shown in lines 77 and 82 have the potential to cause problems that the other way does not ?

While interface declarations allow the use of untyped string constants for the GUID other use cases like conversion in function parameters (like IInterface.QueryInterface) do not. While one could declare a operator overload for that, the conversion that the compiler does also checks for correct syntax of the GUID and thus avoids potential mistakes.

I think the problem is that TGUIDs can't be true constants because they are too large.

I'm not sure how much identity Corba actually supports.
They can be if you followed my advice and patch activex.pp to compile the typed constants in {$J-} state.
Then they end up in rodata and are by definition immutable.
Maybe you did not read that thread yet? It contains a patch.
I respect that you can not read everything and can reprovide the patch again.

That doesn't make them true constants (as marcov meant) in the sense of not part of either the .rodata or the .data section.

Yes, but in the case of COM that is syntax, not how the GUID is interpreted.
Or is that what you mean? A COM GUID is binary and the compiler takes care of that.

While TGUID originates from COM a GUID does not need to be used with COM. Thus the implicit conversion of string constants to TGUID for purpose of initialization is simply a convenience of that type.

 

TinyPortal © 2005-2018