web-dev-qa-db-ja.com

SwiftでC文字列を操作する、または:UnsafePointer <CChar>をCStringに変換する方法

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つの理由で満足できるとは言えません。

  • 単純な作業には複雑すぎます。
  • (主な理由:)上記の変換は、C文字列が有効なUTF-8文字列である場合にのみ機能します。それ以外の場合は、ランタイム例外で失敗します。ただし、C文字列は任意の文字のシーケンスであり、NUL文字で区切られます。

備考/背景:もちろん、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
_
26
Martin R

Swift 1.1(またはおそらく以前)には、さらに優れたC文字列ブリッジがあります。

let haystack = "This is a simple string"
let needle = "simple"
let result = String.fromCString(strstr(haystack, needle))

CStringタイプは完全になくなりました。

17
Nate Cook

SwiftのString構造体には、次のように使用できる初期化ルーチンがあります。

let myString = String(cString: myUnsafePointer)

参照 init(cString:UnsafePointer)

0