Delphi XE4 Indy compatibility issue between TBytes and TidBytes

Today I am trying to compile my XE3 project into XE4. The first problem I encountered is the Indy FTCPClient.Socket.ReadBytes () method.

Before he adopted the TBytes type, he now insists on TidBytes.

Definitions: TIdBytes = array of bytes; TBytes, Im not sure what I think is generics like TArray, which is a Byte array.

Question # 1: Why does the compiler complain, saying that "[dcc32 Error] HistoricalStockData.pas (298): E2033 The types of the real and formal parameters of var must be the same." As I see, they are already identical.

Question # 2: Do I have to change the source code with every new version of delphi?

Thanks.

+6
source share
3 answers

The reason TIdBytes was a simple alias for TBytes in earlier versions of Indy 10, mainly for compatibility with SysUtils.TEncoding , which uses TBytes . Indy TIdTextEncoding used for a simple alias for SysUtils.TEncoding in D2009 +, so TIdBytes must be a simple alias for TBytes to match.

However, TBytes caused quite a bit of trouble for Indy in XE3, mainly due to RTTI issues with Generics ( TBytes is a simple alias for TArray<Byte> in recent Delphi releases). So, Indy 10.6 redesigned TIdTextEncoding to no longer rely on SysUtils.TEncoding in general (there were other reasons for this), which then allowed TIdBytes to change their own array type to avoid XE3 questions moving forward.

On the other hand, you went through TBytes where TIdBytes was expected, so this is bad programming on your part in order not to follow the interface defined by Indy in the first place. All operations based on Indy 10, including ReadBytes() , always worked only on TIdBytes . The fact that TIdBytes silently displayed on TBytes was a detail of an implementation that you shouldn't have referenced in your code. Indy 10 expects TIdBytes , so use TIdBytes , then you will not have compiler errors about incompatible types.

+8
source

The next two ads do not match, although they do look. They do not match the assignment , although both are based on an 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 are not the same type, even if both are defined as array of Byte .

Regarding your question 2: This is a common problem with some third-party codes. Indy, in particular, is known for making changes that violate backward compatibility because they decide to reorganize or rewrite things between versions. Indy 10 was a major change from Indy 9, IIRC, and pretty much required rewriting most of the code that used it if you upgraded to a later version of Indy (even without updating Delphi at the same time). If you do not want to deal with these changes, you may need to use a more stable IP communications package. There are several available, which are also free open source packages.

+3
source

In Indy 10.5.9, the TIdBytes type was defined differently depending on the presence of the existing TBytes type - see the IdGlobal block:

  {$IFDEF HAS_TBytes} TIdBytes = TBytes; {$ELSE} TIdBytes = array of Byte; {$ENDIF} 

In Indy 10.6 (included in XE4), the declaration changed to unconditional

  TIdBytes = array of Byte; 

which means that starting with Indy 10.6, IdGlobal.TIdBytes is different from SysUtils.TBytes.

The second question is difficult to answer, it is rather a question of your priorities - other libraries are also not protected from changes, for example, to improve performance or type safety. Also, changes to the Delphi language can always affect existing code.

+2
source

Source: https://habr.com/ru/post/944124/


All Articles