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

问题描述 投票:26回答:2

[在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>,必须将其传递给NSFileManager功能stringWithFileSystemRepresentation,需要CString论点。


更新:从Xcode 6 beta 6开始,此问题不再存在,因为已简化了C字符串到Swift的映射。你可以写

let s1 = "abc"      // String
let s2 = strdup(s1) // UnsafeMutablePointer<Int8>
let s3 = strdup(s2) // UnsafeMutablePointer<Int8>
let s4 = String.fromCString(s3) // String
swift cstring
2个回答
18
投票

Swift 1.1(或更早的版本)具有更好的C字符串桥接:

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

CString类型已完全消失。


0
投票

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

let myString = String(cString: myUnsafePointer)

另请参阅init(cString: UnsafePointer)

© www.soinside.com 2019 - 2024. All rights reserved.