Questions about GUID declarations magic lazarus / 67-Windows ---------------------------------------------------------------------- 440bx · 2025-07-09 10:47 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  {$define USE_DATA_TYPE_IDENTICAL_TO_GUID} program _GUID_Declarations; uses  Windows,  ActiveX  ;  type  { EXACT copy of TGUID definition                                          }   TDATA_TYPE = packed record     case integer of        1 : (             Data1 : DWord;             Data2 : word;             Data3 : word;             Data4 : array[0..7] of byte;            );        2 : (             D1 : DWord;             D2 : word;             D3 : word;             D4 : array[0..7] of byte;            );        3 : ( { uuid fields according to RFC4122 }             time_low : dword;                  // The low field of the timestamp             time_mid : word;                    // The middle field of the timestamp             time_hi_and_version : word;           // The high field of the timestamp multiplexed with the version number             clock_seq_hi_and_reserved : byte;     // The high field of the clock sequence multiplexed with the variant             clock_seq_low : byte;                 // The low field of the clock sequence           node : array[0..5] of byte;           // The spatially unique node identifier            );  end; type  TDATA_TYPE2 = TGUID;  const  { this compiles                                                           }   SOMEGUID  : TGUID        = '{00000114-0000-0000-C000-000000000046}'; const  { this also compiles                                                      }   SOMEGUID2 : TDATA_TYPE2  = '{00000114-0000-0000-C000-000000000046}';  {$ifdef USE_DATA_TYPE_IDENTICAL_TO_GUID}const  { this does NOT compile ... why ??? - TDATA_TYPE is identical to TGUID      }   SOMEGUID2 : TDATA_TYPE = '{00000114-0000-0000-C000-000000000046}';{$endif}  // in activex.pp//// IID_IOleWindow : TGUID = '{00000114-0000-0000-C000-000000000046}';//// IOleWindow = interface(IUnknown)//    ['{00000114-0000-0000-C000-000000000046}']    { <- duplicated value   }////    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^////    this duplicated value opens the door to errors  const  { define IID as plain - untyped - constant                                  }   IID_IOleWindow = '{00000114-0000-0000-C000-000000000046}'; type  { _IOleWindow                                                             }   IOleWindow = interface(IUnknown) [IID_IOleWindow]  { <- use the plain constant }      { methods here }   end; begin   readln;end.                           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. ---------------------------------------------------------------------- Thaddy · 2025-07-09 11:00 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. ---------------------------------------------------------------------- marcov · 2025-07-09 11:09 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 · 2025-07-09 11:12 Quote from: marcov on July 09, 2025, 01:09:48 pmI 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. ---------------------------------------------------------------------- marcov · 2025-07-09 11:13 I'm not really interested in Corba, but what thread exactly ? There is no in your post. ---------------------------------------------------------------------- Thaddy · 2025-07-09 11:15 This one: https://forum.lazarus.freepascal.org/index.php/topic,71688.msg560072.h tml#msg560072 ---------------------------------------------------------------------- marcov · 2025-07-09 11:53 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 · 2025-07-09 12:18 Quote from: marcov on July 09, 2025, 01:53:25 pmThe 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. ---------------------------------------------------------------------- Thaddy · 2025-07-09 13:24 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. ---------------------------------------------------------------------- Thaddy · 2025-07-09 14:26 @Marcov I filed report + patch #41325 ---------------------------------------------------------------------- Thaddy · 2025-07-09 14:28 Quote from: marcov on July 09, 2025, 01:53:25 pmThe 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. ---------------------------------------------------------------------- ASerge · 2025-07-09 18:46 Quote from: 440bx on July 09, 2025, 02:18:30 pmThe 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: QuoteA constant of type TGUID can be specified using a string literal ---------------------------------------------------------------------- Thaddy · 2025-07-09 18:54 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. ---------------------------------------------------------------------- 440bx · 2025-07-09 20:39 Quote from: ASerge on July 09, 2025, 08:46:33 pmThis is documented in Interface identification: A GUID: QuoteA constant of type TGUID can be specified using a string literalSomehow 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. ---------------------------------------------------------------------- PascalDragon · 2025-07-09 21:10 Quote from: 440bx on July 09, 2025, 12:47:52 pmIt 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). Quote from: 440bx on July 09, 2025, 12:47:52 pmThere 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. Quote from: Thaddy on July 09, 2025, 01:12:11 pmQuote from: marcov on July 09, 2025, 01:09:48 pmI 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. Quote from: Thaddy on July 09, 2025, 08:54:57 pmYes, 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. ---------------------------------------------------------------------- 440bx · 2025-07-09 21:44 Thank you for the clarifications PascalDragon. ---------------------------------------------------------------------- Thaddy · 2025-07-10 15:07 Quote from: PascalDragon on July 09, 2025, 11:10:00 pmThat doesn't make them true constants (as marcov meant) in the sense of not part of either the .rodata or the .data section.I know, but it is correct to make those guids immutable. That's the whole issue. These particular guid consts are part of the COM specification, subs. Windows API.