【问题标题】:'withUnsafeBytes' is deprecated warning when passing void* argument to c function in swift 5在 swift 5 中将 void* 参数传递给 c 函数时,不推荐使用“withUnsafeBytes”警告
【发布时间】:2019-08-21 17:27:24
【问题描述】:

我有一个使用外部提供的 c 库快速解析 FIT 文件的库。解析函数将void * data 作为参数。 为了调用该函数,我使用 data.withUnsafeBytes( { (ptr: UnsafePointer<UInt8>) in ...} 转换数据以构建 c 函数的参数,它工作正常。

Xcode 升级到 swift 5 后,我现在收到一个弃用的警告

'withUnsafeBytes' 已弃用:改用withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R

我不知道如何修复代码以删除已弃用的警告。代码一直运行良好,在 swift 4 中没有警告

我尝试将闭包中的参数更改为采用 UnsafeRawBufferPointer 而不是 UnsafePointer,但这导致调用函数时出错:Cannot convert 'UnsafeRawBufferPointer' to expected argument type 'UnsafeRawPointer?'

这是一个显示问题的小 swift 文件:

import Foundation

// Create sample data (Typically would be read from a file
let data = Data(repeating: 1, count: 10)

data.withUnsafeBytes( { (ptr : UnsafePointer<UInt8>) in
    // call the c function with the void* argument
    let value = readFITfile(ptr)
    print( value )
})

还有一个例子c函数

unsigned readFITfile(const void * data){
    //Silly example to show it works, just returning the value of pointer as int
    //Typically would parse the data and return a structure
    return (unsigned)data;
}

我用上面的代码在https://github.com/roznet/swift2c 保存了一个小仓库,解析文件的完整项目在这里https://github.com/roznet/fit-sdk-swift

【问题讨论】:

    标签: c swift unsafe-pointers


    【解决方案1】:

    您必须将闭包参数更改为UnsafeRawBufferPointer,然后取其baseAdress(这是UnsafeRawPointer?,在C 中相当于void * 的Swift):

    data.withUnsafeBytes( { (ptr : UnsafeRawBufferPointer) in
        let value = readFITfile(ptr.baseAddress)
        // ...
    })
    

    Swift 编译器还可以自动推断闭包参数类型:

    data.withUnsafeBytes( { ptr in
        let value = readFITfile(ptr.baseAddress)
        // ...
    })
    

    有关此问题的更多信息,请参阅 Swift 论坛中的withUnsafeBytes Data API confusion

    【讨论】:

      【解决方案2】:

      现在要获取 UnsafePointer,您应该这样做

      data.withUnsafeBytes { (ptr: UnsafeRawBufferPointer) in
          if let ptrAddress = ptr.baseAddress, ptr.count > 0 {
              let pointer = ptrAddress.assumingMemoryBound(to: UInt8.self) // here you got UnsafePointer<UInt8>
              let value = readFITfile(ptr)
              print( value )
          } else {
              // Here you should provide some error handling if you want ofc
          }
      }
      

      【讨论】:

      • 给定的 C 函数采用 void * 参数,无需将 UnsafeRawPointer 转换为 UnsafePointer&lt;UInt8&gt;
      • 顺便说一句,ptr.baseAddress 不能为非空缓冲区指针的nil
      猜你喜欢
      • 2019-08-18
      • 2019-12-16
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多