在Swift </char_t>中将String转换为UnsafeMutablePointer <char_t>

时间:2014-12-31 01:32:20

标签: swift cstring

我正在使用第三方c API我试图用简单的字符串调用其中一个函数。像这样:

some_c_func("aString");

我收到了构建错误:

Type 'UnsafeMutablePointer<char_t>' does not conform to protocol 'StringLiteralConvertible'

我已经看到一些建议在字符串或类似的转换上使用utf8,它几乎就在那里,但出现以下错误:

some_c_func("aString".cStringUsingEncoding(NSUTF8StringEncoding));
'UnsafePointer<Int8>' is not convertible to 'UnsafeMutablePointer<char_t>'

如何创建UnsafeMutablePointer?

3 个答案:

答案 0 :(得分:2)

这完全取决于char_t是什么。

如果char_t转换为Int8,则以下内容将有效。

if let cString = str.cStringUsingEncoding(NSUTF8StringEncoding) {
    some_c_func(strdup(cString))
}

这可以折叠为

some_c_func(strdup(str.cStringUsingEncoding(NSUTF8StringEncoding)!))

警告! 如果func cStringUsingEncoding(_:)返回nil,则第二种方法会导致崩溃。


更新Swift 3,并修复内存泄漏

如果只在本地范围内需要C字符串,则不需要strdup()

guard let cString = str.cString(using: .utf8) else {
    return
}

some_c_func(cString)

cString将具有与str相同的内存生命周期(至少相似)。

如果C字符串需要在本地范围之外,那么您将需要一个副本。该副本需要被释放。

guard let interimString = str.cString(using: .utf8), let cString = strdup(interimString) else {
    return
}

some_c_func(cString)

//…

free(cString)

答案 1 :(得分:1)

它可能比那更简单 - 许多C API将字符串作为char *类型传递,swift将这些视为不安全。

尝试更新C API(好)或破解它的头文件(坏),将它们声明为const char *。

根据我的经验,这允许您将标准swift String类型直接传递给C API。

显然需要一个常数,以符合协议。

答案 2 :(得分:0)

我还没有尝试过这样的字符串,但我有一个我从Swift调用的C函数,它需要的参数比这里显示的要多得多,其中包括一个Swift C类型转换缓冲区的引用错误字符串。编译器没有抱怨并且函数调用有效。希望这会引导您更接近答案,您可以提供最终答案的更新或其他人可以。

    var err = [CChar](count: 256, repeatedValue: 0)
    var rv = somefunc((UnsafeMutablePointer<Int8>)(err))

    if (rv < 0) {
        println("Error \(err)")
        return
    }