【问题标题】:Convert String to UnsafeMutablePointer<char_t> in Swift在 Swift 中将字符串转换为 UnsafeMutablePointer<char_t>
【发布时间】:2015-02-27 04:24:57
【问题描述】:

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

【问题讨论】:

    标签: swift cstring


    【解决方案1】:

    这完全取决于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)
    

    【讨论】:

    • 这行得通,谢谢!但它不再(不再?)需要可选的展开。 cStringUsingEncoding 上的签名是func cStringUsingEncoding(encoding: UInt) -&gt; UnsafePointer&lt;Int8&gt;,strdup 只是将其转换为 UnsafeMutablePointer。
    • @brodney heh,我正在使用 Xcode 6.1.1 工具 (6A2008a):签名是 func cStringUsingEncoding(encoding: NSStringEncoding) -&gt; [CChar]?,降级为 UnsafePointer&lt;Int8&gt;?
    • 使用 strdup,您必须释放缓冲区。推迟{免费(cString)}
    • @RomainTAILLANDIER 感谢您的协助。
    【解决方案2】:

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

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

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

    为了符合协议,显然需要一个常量。

    【讨论】:

    • 太棒了!你在这方面帮了我很大的忙。由于将 String 转换为 UnsafeMutablePointer 并返回,我丢失了许多上下文。 strdup 看起来很脏,而且不容易解除分配(以及解除分配的位置)。传统知识
    【解决方案3】:

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

        var err = [CChar](count: 256, repeatedValue: 0)
        var rv = somefunc((UnsafeMutablePointer<Int8>)(err))
    
        if (rv < 0) {
            println("Error \(err)")
            return
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 2018-10-21
      • 2015-06-15
      • 1970-01-01
      相关资源
      最近更新 更多