2017-09-25 15 views
3

dispatch IO channelを使用して、ファイル記述子から一部のデータを読みたいとします。チャンネルを作成したら、次のステップは、その宣言は次のようであるreadを呼び出すことです:Swift GCDオーバーレイでのタイプの不一致

func read(offset: off_t, 
    length: Int, 
    queue: DispatchQueue, 
ioHandler: @escaping (Bool, DispatchData?, Int32) -> Void) 

lengthパラメータのドキュメントは言う:

The number of bytes to read from the channel. Specify SIZE_MAX to continue reading data until an EOF is reached.

は十分に簡単に思えます。私の場合、私はちょうどそれをしたいです - EOFまで読む。だから私はSIZE_MAXを渡します:

// `queue` and `handler` defined elsewhere 
channel.read(offset: 0, length: SIZE_MAX, queue: queue, ioHandler: handler) 

賢明な読者は、コンパイラはこれを好きではないことを推測しています

Cannot convert value of type 'UInt' to expected argument type 'Int'

SIZE_MAXタイプUIntのですが、lengthはタイプIntです。コンパイラはそれを修正するために提供しています:

channel.read(offset: 0, length: Int(SIZE_MAX), queue: queue, ioHandler: handler) 

しかし、もちろん、実行時に、これはとてもうまく動作しません:

fatal error: Not enough bits to represent a signed value

を当然SIZE_MAXUIntによって最大値の表現であれば、その後、Intそれを表現することはできません。いくつかのクイック検索の後、私はthis exact issue on the Swift bug trackerを見つけました。それはまだ解決されていないようで、プルリクエストで自分自身で解決する能力が不明です。どうすればこの問題を回避できますか?それとも、私が欲しいことをするための方法が欠けていますか?


スウィフトStdlibの理論的根拠ドキュメントcovers the explicit decision to import size_t as Int rather than UInt。 「より少ないタイプの変換」と、とにかく2^63を超える数を指定する必要がある(残念ながら、32ビットプラットフォーム)。十分に公正ですが、それはSIZE_MAXの使用がAPIの一部である私のような問題をカバーしません。

+0

'length:Int(bitPattern:SIZE_MAX)'を渡しても問題ありませんか? –

+0

それかもしれません!少なくともコンパイルしてもクラッシュしません。正直なところ、私はまだこれをテストする合理的な方法を考え出していない。私は正確に2^64バイトのデータストリームを作成することはできませんし、SwiftからCへのインターフェイスで 'Int'が' size_t'にどのように変換されるのかについての実体的な扱いはありません。 – ravron

答えて

2

ちょうど使用Int.maxもしあなたが64ビットプラットフォームを使用しているのであれば、Int.maxバイトを読む前にファイルの終わりに達することがほぼ確実です。 32ビットプラットフォームでは、ファイルが非常に大きい場合は、複数の読み取りを発行する必要があります。

あなたはAppleに問題を報告する必要があります。 Dispatch IOライブラリがAppleかSwift Open Sourceプロジェクトに属しているのか、それとも単なるドキュメントのエラーなのかわかりません。

更新

ソースコードは、オープンソースであり、読み出し動作は、長さsize_tを取るC関数への単純なラッパーです。

https://github.com/apple/swift-corelibs-libdispatch/blob/master/src/swift/IO.swift

私はそれを試していないが、しかし、あなたはほぼ確実に、おそらくビットパターン、あるいは-1を使用することができます。私はまだInt.maxと一緒に行くと思います。

+0

私は 'Int(bitPattern:SIZE_MAX)'をダミーのC関数に 'size_t'として渡してテストしました。実際に期待通りに動作し、その引数はCの' SIZE_MAX 'と同じです。 。 – ravron