Indy Changed from Indy10
Http://stackoverflow.com/questions/16339656/delphi-xe4-indy-compatibility-issue-between-tbytes-and-tidbytes
Http://stackoverflow.com/questions/19402374/delphi-xe3-indy-compatibility-issue-between-tbytes-and-tidbytes
Http://stackoverflow.com/questions/18849053/how-should-i-adapt-my-code-for-compatibility-between-tbytes-and-tidbytes
Today I try to compile my XE3 project in XE4. First problem that I-face was with Indy ' s FTCPClient.Socket.ReadBytes () method.
Before it is accepting tbytes type, now it insists on tidbytes.
Definitions:tidbytes = array of Byte; Tbytes, Im Not sure I guess it's generics something like Tarray which is array of Byte.
Question number 1:why does compiler complain by saying that ' [Dcc32 Error] Historicalstockdata.pas (298): E2033 Types of AC Tual and formal var parameters must be identical '. As I see they is already identical.
Question number 2:should I modify my source code with the each new Delphi version?
Thanks.
Answers:
The reason Tidbytes is a simple alias for Tbytes in earlier Indy releases is primarily for compatibility with SysUtil S.tencoding, which uses tbytes. Indy ' s tidtextencoding type used to is a simple alias for sysutils.tencoding in d2009+, so tidbytes needed to being a simple Alias for Tbytes to match.
However, Tbytes caused quite a bit of trouble for Indy in XE3, mainly because of RTTI problems with generics (Tbytes is a Simple alias for tarray<byte> in recent Delphi releases). So, Indy 10.6 re-designed tidtextencoding to no longer rely on sysutils.tencoding @ all (there were other reasons as well for doing so), which then allowed Tidbytes-to-change-to-its-own array type in order to avoid the XE3 issues moving FORW Ard.
On the other hand, you were passing a tbytes where a tidbytes were expected, so that's bad programming on your T following Indy ' s defined interface in the first place. All of Indy ' s byte-based operations, including Readbytes (), with always operated on tidbytes only. The fact that tidbytes silently mapped to tbytes is an implementation detail so you should not having relied on your C Ode. Indy expects tidbytes, so use tidbytes and then you would not having compiler errors about incompatible types.
Share|improve this Answer
Edited 2 ' at 17:18
answered 2 ' at 16:24
Remy LeBeau
149k882162
1
Libraries that invent their own types instead of the using equivalent RTL types just leads to ghettoisation. How can we write code this uses Indy and its byte array and interacts with the another library using its byte array? –david Heffernan 4 ' at 0:31
First tell Embarcadero to stop breaking their own products when they make RTL changes. Tbytes used to bes a simple dynamic array (like Tidbytes is now). It worked great with RTTI, Object Inspector, compiler, etc. Then they switched tbytes to tarray<byte> and broke all of this (bad generics RTTI, bad C + + CodeGen, etc). Also Remember that Indy supports multiple languages, and tarray<t> works differently in C + + than in Delphi. So there were multiple reasons for making tidbytes go back to a simple dynamic array. I didn ' t make the change lightly, and even Embarcadero recommended I did it at the time. –remy LeBeau 4 ' at 3:13
OK, I ' m sure you had good the reason to the change. It feels all wrong to me, there ' s still debate over how to handle byte arrays. The "right" solution, assuming everything could is made to work, would is for all code to use tarray<t> directly and So enjoy the special type compatibility rules for generic types. Ideal world there would is no tbytes, no tidbytes, and libraries could happily co-exist and interact smoothly. –david Heffernan 4 ' at 14:52
The following declarations is not the same and even though they appear to be. They ' re not assignment compatible, even though they ' re both based on array of string.
Type
Tstringarrayone = array of string;
Tstringarraytwo = array of string;
Var
AVar1, Avar2:tstringarrayone;
AVar3, Avar4:tstringarraytwo;
Begin
AVAR1: = Tstringarrayone.create (' A ', ' B ', ' C '); Compiles
AVAR2: = Tstringarraytwo.create (' A ', ' B ', ' C '); Won ' t compile
AVAR3: = Tstringarraytwo.create (' A ', ' B ', ' C '); Compiles
AVAR4: = Tstringarrayone.create (' A ', ' B ', ' C '); Won ' t compile
End
So tbytes and tidbytes is not the same type, even if they ' re both defined as being array of Byte.
With regard to your question 2:it ' s a common problem with some third-party code. Indy in particular are known for making changes, breaks backward compatibility because they decide to reorganize or rew Rite things between versions. Indy is a major change from Indy 9, IIRC, and pretty much required a rewrite of the most code that used it if you updated To the later version of Indy (even without updating Delphi at the same time). If you don ' t want-deal with those changes, you might want-to-look at using-a more stable-IP communications package. There is several available that is also free, open source packages.
In Indy 10.5.9 the type tidbytes is defined differently depending on the presence of an existing tbytes Type-see unit I Dglobal:
{$IFDEF Has_tbytes}
Tidbytes = tbytes;
{$ELSE}
Tidbytes = array of Byte;
{$ENDIF}
In Indy 10.6 (included-XE4), the declaration changed to unconditionally
Tidbytes = array of Byte;
Which means that starting with Indy 10.6, idglobal.tidbytes are different from sysutils.tbytes.
The second question was hard to answer, it was more a question of your priorities-other libraries was not immune against C Hanges either, for example to improve performance or type-safety. Also changes in the Delphi language can always affect existing code.
Question2:
3
Down vote
Favorite
I am have the same problem as mentioned in "Delphi XE4 Indy compatibility issue between Tbytes and tidbytes", i.e. comp Atibility Issues between Tbytes (Delphi RTL) and Tidbytes (Indy) datatypes when compiling with the Delphi XE4. The source of my problem is, the code was not exactly according to Indy's interface and some of functions use tbytes, I Nstead of Tidbytes, when calling native Indy IO procedures.
So I am wondering what would the best fix be?
As I see it there is approaches:
1.Refactor all functions in the project to use Tidbytes rather than tbytes.
2.Implement a tbytestotidbytes conversion procedure (converts the tbytes to tidbytes) and call that procedure prior to MAK ing the mentioned native Indy calls.
Which of the approaches is better/best? Does any of the other ideas in how can I?
Fyi:the Project I am trying to configure with the XE4 are available online on Sourceforge:http://sourceforge.net/project S/indy10clieservr/?source=directory
The suggested conversion procedure should is something like:
Procedure Tbytestotidbytes (const input:tbytes, var output:tidbytes)
Var
I,l:integer;
Allocate:boolean;
Begin
L: = Length (Input);
if (Length (Output) <> L) Then
Begin
SetLength (output,l);
End
if (L > 0) Then
Move (Pointer (Input) ^,pointer (Output) ^,l);
End
Answer:
Tbytes and Tidbytes are both implemented as dynamic arrays, they is simply declared differently. The "politically correct" solution is a copy of the bytes. But the can waste memory for large arrays. A simpler solution is to use a typecast so can utilize the array ' s internal reference count, eg:
Type
Pidbytes = ^tidbytes;
Var
B1:tbytes;
B2:tidbytes;
Begin
B1: = ...;
B2: = Pidbytes (@B1) ^;
End
Or simply:
Var
B1:tbytes;
B2:tidbytes;
Begin
B1: = ...;
B2: = Tidbytes (B1);
End
Both types is not the same at implementation level, newer Delphi versions (Tbytes was a simple alias for Tarray<byte > in recent Delphi releases).
So I guess you can use such a procedure:
Procedure Tbytestotidbytes (const input:tbytes; var output:tidbytes);
var L:integer;
Begin
L: = Length (Input);
SetLength (output,l);
Move (INPUT[0],OUTPUT[0],L);
End
Here move () is faster than a loop.
Indy Changed from Indy10