2013-05-02 35 views
6

今日私はXE3で自分のXE3プロジェクトをコンパイルしようとしています。私が直面する最初の問題は、IndyのFTCPClient.Socket.ReadBytes()メソッドです。Delphi XE4 TBytesとTidBytesの間のIndyの互換性の問題

TBytesタイプを受け入れる前に、今はTidBytesを主張しています。

説明: TIdBytes = Byteの配列。 TBytes、Im私はそれがByteの配列であるTArrayのようなジェネリックなものだとは思わない。

質問番号1: なぜコンパイラは '[dcc32 Error] HistoricalStockData.pas(298):E2033実際のパラメータと正式なvarパラメータの型が同じである必要があります。私が見るとおり、彼らはすでに同じです。

質問番号2: 新しいデルファイバージョンでソースコードを変更する必要がありますか?

ありがとうございました。

答えて

8
TIdBytes

理由は、以前のインディ10のリリースでTBytesための単純なエイリアスでした。 IndyのTIdTextEncodingタイプはD2009 +のSysUtils.TEncodingの単純なエイリアスだったので、TIdBytesTBytesの単純なエイリアスである必要がありました。

はしかし、TBytesは、主にジェネリック医薬品とのRTTIの問題(TBytesが、最近のDelphiのリリースでTArray<Byte>するための単純なエイリアスである)の、XE3でインディのためのトラブルのかなりのビットを引き起こしました。したがって、Indy 10.6はTIdTextEncodingをもう一度SysUtils.TEncodingに依存しないように再設計しました(他の理由もありました)ので、XE3の問題を回避するためにTIdBytesを独自の配列タイプに変更することができました。

一方、TIdBytesが期待されていたTBytesを渡していたため、最初にIndyの定義済みのインターフェイスに従わなかったためにプログラミングが悪いです。 ReadBytes()を含むIndy 10のすべてのバイトベースの操作は、常にTIdBytesでのみ動作しています。 TIdBytesが暗黙のうちにTBytesにマップされているという事実は、コードに頼ってはいけない実装の詳細です。 Indy 10はTIdBytesを期待しているので、TIdBytesを使用すると、互換性のない型に関するコンパイラエラーは発生しません。

+4

同等のRTL型を使用するのではなく、独自の型を作成しているライブラリは、ゲットーにつながります。 Indyとそのバイト配列を使用し、バイト配列を使用して別のライブラリとやりとりするコードをどうやって書くことができますか? –

+0

まず、RTLを変更したときにEmbarcaderoが自社製品の中断を止めるように指示します。 TBytesは単純な動的配列でした(今のところTIdBytesはそうです)。 RTTI、Object Inspector、コンパイラなどでうまくいきました。そして、TBytesをTArray に変更し、そのすべてを破棄しました(Generics RTTIが悪い、C++のcodegenが悪いなど)。また、Indyは複数の言語をサポートしており、TArray はC++とDelphiでは異なる動作をすることに注意してください。そこで、TI dBytesを単純な動的配列に戻すための複数の理由がありました。私は軽く変更を加えなかったし、Embarcaderoでも私がその時にやるよう勧めた。 –

+3

OK、私はあなたが変更する正当な理由があったと確信しています。 2013年にバイト配列を扱う方法についての議論がまだ残っていると私は間違っています。すべてのコードが 'TArray 'を直接使用しているので、すべてのコードが一般的な型のための特別な型互換性の規則を楽しむことができます。したがって、理想的な世界では、「TBytes」も「TIdBytes」もなく、ライブラリは幸せに共存し、スムーズにやり取りすることができます。 –

3

ではなく、のように表示されます。どちらもarray of stringに基づいていますが、それらはassignment compatibleではありません。

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; 

のでTBytesTIdBytes彼らは両方array of Byteあるものとして定義されている場合でも、同じタイプではありません。

ご質問について2:サードパーティ製のコードによくある問題です。 Indyは特に、バージョン間で物事を再編成したり書き換えたりすることを決めたため、下位互換性を損なう変更を加えることで知られています。 Indy 10はIndy 9、IIRCからの大きな変更であり、Indyの最新バージョン(Delphiを同時に更新しなくても)に更新した場合は、ほとんどのコードを書き直す必要がありました。これらの変更に対処したくない場合は、より安定したIP通信パッケージを使用することを検討してください。無料のオープンソースパッケージもいくつかあります。

+0

合意されています。 :-) –

+1

私はそれを楽しんでいないと誰が言ったのですか? ;-) –

2

インディ10.5.9で型TIdBytesは、既存のTバイトのタイプの存在に応じて異なって定義された - ユニットIdGlobal参照:インディ10.6で

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

を(XE4に含まれる)、宣言は無条件に変更

TIdBytes = array of Byte; 

インディ10.6始まる、IdGlobal.TIdBytesはSysUtils.TBytes異なっていることを意味します。

2番目の質問に答えるのは難しいです。優先順位の問題です。他のライブラリは、パフォーマンスや型の安全性を向上させるなど、変更に対する影響はありません。また、Delphi言語の変更は、既存のコードに影響を与える可能性があります。 TBytesを使用する、SysUtils.TEncodingとの互換性のために主に