我正在使用第三方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?
答案 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
}