On Friday I had a brain fade moment (which I don't seems to have recovered from). I'm coding up app to help people find and implement OTA code and the app uses TVirtualStringTree (a lot). So I defined a record for the tree as:
On Friday I had a brain fade moment (which I don't seems to have recovered from). I'm coding up app to help people find and implement OTA code and the app uses TVirtualStringTree (a lot). So I defined a record for the tree as:
Type
TTreeData = Record
...
End;
I've then been referring to the record as follows:
Var
NodeData : ^TTreeData;
Which allows my to do:
...
NodeData := vstInterfaces.GetNodeData(Node);
NodeData.FFileIndex := ....
...
I then wanted to pass the record to another function and since you can't define pointers to types in a function I created this type:
Type
PTreeData = ^TTreeData;
Then the function:
Procedure MyFunc(NodeData : PTreeData);
However I could not pass NodeData as defined above (^TTreeData) to this function without redefining it as:
Var
NodeData : PTreeData;
In my mind they are the same but the compiler obviously believes they are different.
Question it why?
Type
TTreeData = Record
...
End;
I've then been referring to the record as follows:
Var
NodeData : ^TTreeData;
Which allows my to do:
...
NodeData := vstInterfaces.GetNodeData(Node);
NodeData.FFileIndex := ....
...
I then wanted to pass the record to another function and since you can't define pointers to types in a function I created this type:
Type
PTreeData = ^TTreeData;
Then the function:
Procedure MyFunc(NodeData : PTreeData);
However I could not pass NodeData as defined above (^TTreeData) to this function without redefining it as:
Var
NodeData : PTreeData;
In my mind they are the same but the compiler obviously believes they are different.
Question it why?
The problem $T is that it's a two-edged sword as it makes code that looks valid fail to compile because the compiler in the $T+ state (a.k.a. $TypedAddress on state) never got updated to:
ReplyDelete- handle @ to an array create a pointer to the element of that array
- handle @ to resourcestrings to become PResStringRec
(and likely more examples)
Which means the below programs fail to compile.
The alternative (adding way more {$T+} compatible overloads to the RTL/VCL/FMX) was never done either, so now we're stuck with {$T-}
program TypedAddressDirectiveWithCharArrays;
{$APPTYPE CONSOLE}
{$TypedAddress on}
uses
Winapi.Windows;
var
TimeZone: string;
TZ: TTimeZoneInformation;
begin
TimeZone := 'Coordinated Universal Time';
StringToWideChar(TimeZone,@(TZ.StandardName), SizeOf(TZ.StandardName) div SizeOf(WideChar));
end.
(*
[dcc32 Error] TypedAddressDirectiveWithCharArrays.dpr(16): E2010 Incompatible types: 'PWideChar' and 'Pointer'
In the System unit:
implicit types:
PWideChar = WideChar;
PChar = PWideChar
explicit:
function StringToWideChar(const Source: UnicodeString; Dest: PWideChar; DestSize: Integer): PWideChar;
In the Winapi.Windows unit:
type
WCHAR = WideChar;
PTimeZoneInformation = ^TTimeZoneInformation;
_TIME_ZONE_INFORMATION = record
Bias: Longint;
StandardName: array[0..31] of WCHAR;
StandardDate: TSystemTime;
StandardBias: Longint;
DaylightName: array[0..31] of WCHAR;
DaylightDate: TSystemTime;
DaylightBias: Longint;
end;
TTimeZoneInformation = _TIME_ZONE_INFORMATION;
TIME_ZONE_INFORMATION = _TIME_ZONE_INFORMATION;
*)
program TypedAddressDirectiveWithResourceStrings;
{$APPTYPE CONSOLE}
{$TypedAddress on}
uses
System.SysConst,
System.SysUtils;
procedure RangeError;
begin
raise ERangeError.CreateRes(@SRangeError);
end;
begin
end.
(*
[dcc32 Error] TypedAddressDirectiveWithResourceStrings.dpr(13): E2250 There is no overloaded version of 'CreateRes' that can be called with these arguments
System unit:
type
PResStringRec = ^TResStringRec;
{$IF defined(EXTERNALLINKER)}
TResStringRec = record
Key: MarshaledAString;
end;
{$ELSE}
TResStringRec = packed record
// 32bit = 8 bytes
// 64bit = 16 bytes
Module: ^HMODULE;
Identifier: NativeUint;
end;
{$ENDIF}
System.SysConst unit:
resourcestring
SRangeError = 'Range check error';
SysUtils unit:
constructor Exception.CreateRes(ResStringRec: PResStringRec);
begin
FMessage := LoadResString(ResStringRec);
end;
*)
Jeroen Wiert Pluimers Is there a QP for that?
ReplyDeleteDavid Millington probably not. It's from the era that beta forum postings and QC entries started to be ignored so after I saw entries http://qc.embarcadero.com/wc/qcmain.aspx?d=3223 it was OK for me.
ReplyDelete