Swiftで標準Cライブラリ関数を操作しているときに、C文字列を渡すときに問題が発生しました。単純な例として(問題を示すためだけに)、標準Cライブラリ関数
_char * strdup(const char *s1);
_
としてSwiftに公開されます
_func strdup(_: CString) -> UnsafePointer<CChar>
_
つまり、strdup()
の戻り値を別のstrdup()
呼び出しに渡すことはできません。
_let s1 : CString = "abc"
let s2 = strdup(s1) // OK, s2 is a UnsafePointer<CChar>
let s3 = strdup(s2) // error: could not find an overload for '__conversion' that accepts the supplied arguments
_
私の質問は:_UnsafePointer<CChar>
_からSwift CString
を作成する方法1つの標準ライブラリ関数によって返されたC文字列を別の関数に渡すことができますか?
私が見つけることができる唯一の方法は次のとおりです( -Swift言語で文字列をCStringに変換するにはどうすればよいですか? のコードを使用します):
_let s2a = String.fromCString(s2).bridgeToObjectiveC().UTF8String
let s3 = strdup(s2a)
_
しかし、これは2つの理由で満足できるとは言えません。
備考/背景:もちろん、Swift String
のような高レベルのデータ構造を使用する高レベルの関数Objective-C NSString
が推奨されます。しかし、標準Cライブラリには、Foundationフレームワークに正確に対応するものがないBSD関数があります。
答えようとしたときにこの問題に遭遇しました Swiftのtempディレクトリにアクセスしています 。ここで、mkdtemp()
は、正確なNSFileManager
置換が存在しない(私の知る限り)BSD関数です。 mkdtemp()
は、NSFileManager
引数を受け取るstringWithFileSystemRepresentation
関数CString
に渡す必要がある_UnsafePointer<CChar>
_を返します。
更新:Xcode 6ベータ6以降、C-StringのSwiftへのマッピングが簡略化されたため、この問題は存在しなくなりました。あなただけ書くことができます
_let s1 = "abc" // String
let s2 = strdup(s1) // UnsafeMutablePointer<Int8>
let s3 = strdup(s2) // UnsafeMutablePointer<Int8>
let s4 = String.fromCString(s3) // String
_
Swift 1.1(またはおそらく以前)には、さらに優れたC文字列ブリッジがあります。
let haystack = "This is a simple string"
let needle = "simple"
let result = String.fromCString(strstr(haystack, needle))
CString
タイプは完全になくなりました。
SwiftのString構造体には、次のように使用できる初期化ルーチンがあります。
let myString = String(cString: myUnsafePointer)