在Swift中使用C字符串,或者:如何将UnsafePointer <cchar>转换为CString </cchar>

时间:2014-06-25 21:32:15

标签: swift 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

我的问题是:如何从CString创建Swift UnsafePointer<CChar>, 这样一个标准库函数返回的C字符串可以传递给另一个函数吗?

我能找到的唯一方法是(使用How do you convert a String to a CString in the Swift Language?中的代码):

let s2a = String.fromCString(s2).bridgeToObjectiveC().UTF8String
let s3 = strdup(s2a)

但我认为这并不令人满意,原因有两个:

  • 对于简单的任务来说太复杂了。
  • (主要原因:)只有当C字符串是有效的UTF-8时,上述转换才有效 字符串,否则失败并出现运行时异常。但是C字符串是任意 字符序列,由NUL字符分隔。

备注/背景:当然,使用Swift String或Objective-C NSString等高级数据结构的高级函数更可取。但是有BSD功能 标准C库,在Foundation框架中没有完全对应的。

我在尝试回答Accessing temp directory in Swift时遇到了这个问题。 这里,mkdtemp()是一个BSD函数,不存在精确的NSFileManager替换 (我所知道的)。  mkdtemp()返回UnsafePointer<CChar>,必须将其传递给。{1}} NSFileManager函数stringWithFileSystemRepresentationCString 参数。


更新:从Xcode 6 beta 6开始,这个问题不再存在,因为C-Strings到Swift的映射已经简化了。你可以写

let s1 = "abc"      // String
let s2 = strdup(s1) // UnsafeMutablePointer<Int8>
let s3 = strdup(s2) // UnsafeMutablePointer<Int8>
let s4 = String.fromCString(s3) // String

2 个答案:

答案 0 :(得分:17)

Swift 1.1(或者可能更早)有更好的C字符串桥接:

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

CString类型已完全消失。

答案 1 :(得分:0)

Swift中的String结构具有一个初始化例程,您可以像这样使用它:

let myString = String(cString: myUnsafePointer)

另请参阅init(cString: UnsafePointer)