CとSwift両方大好きな皆様こんにちは。本稿では、Swiftでchar **
をうまく扱う方法について考えてみます。
確かにSwiftでのchar *の取り扱いは悪くない
先駆者の方々の指摘通り、SwiftのString
型とCのchar *
型との相互変換はそれなりに整備されていると言えそうです。
String#withCString
とString#fromCString
あたりを知っていればSwiftからCのシステムコール・ライブラリコールを便利に利用できるはずです。
ところでchar **は…?
ところで、Cのシステムコール・ライブラリコールにはchar **
を引数に取るものがあり、Swiftからも利用できます。たとえばSwiftのposix_spawn
の第5引数argv
の型は次のようなものです。
UnsafePointer<UnsafeMutablePointer<Int8>>>
これはCで言うとchar *const *
に対応しますが、これを[Stirng]
とを相互変換したいときにどうすればいいのか、というのはあまり議論されていないように思います。途方に暮れた末、筆者はGistに落ちていたCStringArray
クラスを改造して使うことにしました。
CStringArray
今回利用したCStringArrayクラスはCocoa Touch Frameworkとして作成しており、Carthageでインストールすることができます。
CStringArrayはコンストラクタ引数に[String?]
を取り、メンバ変数pointers
でchar *const *
が取り出せます。下記は使用例です。
let argv = CStringArray(["/bin/ls", "-la" , "/", nil])
posix_spawn(&pid, argv.pointers[0], &action, nil, argv.pointers, nil)
pointers
はUnsafeMutablePointer<CChar>
の配列なので、必要であればcount
で個数も取り出せます。
&argv.pointers
とすればchar **
と互換になりますが、実装上pointers
を書き換えられるとメモリリークしてしまうのでchar *const *
で取り扱うのが無難だと思います。
参考URL
- 今回の実装: https://github.com/hnw/CStringArray/blob/master/CStringArray/CStringArray.swift
- 元の実装: https://gist.github.com/neilpa/b430d148d1c5f4ae5ddd
ご意見募集
実はこんなゴテゴテしたクラスを作らなくても綺麗に解決できるのかもしれません。Swift初心者なので、プロの方のご意見をお待ちしております。