将Swift String数组转换为c char **

问题描述 投票:1回答:1

我正在从Swift 4调用一个C库,我遇到了将[String]转换为const char *[]的麻烦。

C API定义了这个方法:

int getDREFs(const char* drefs[], unsigned char count);

在Swift中曝光的

public func getDREFs(_ drefs: UnsafeMutablePointer<UnsafePointer<Int8>?>!, _ count: UInt8) -> Int32

我正在尝试编写的Swift包装器如下

public func get(drefs: [String]) throws {

    var cDrefs = [UnsafePointer<Int8>]()
    for dref in drefs {
        cDrefs.append(dref.cString(using: .utf8)!)
    }
    let pDrefs = UnsafeMutablePointer<UnsafePointer<Int8>>(&cDrefs)
    getDREFFs(pDrefs, drefs.count)

}

但我得到的错误是

Cannot convert value of type 'UnsafeMutablePointer<UnsafePointer<Int8>>' to expected argument type 'UnsafeMutablePointer<UnsafePointer<Int8>?>!'

我错过了什么?

c arrays swift
1个回答
1
投票

getDREFSs期望一个指向可选Int8指针数组的指针。第二个参数也必须转换为UInt8

所以这将编译:

public func get(drefs: [String]) -> Int {
    var cDrefs = [UnsafePointer<Int8>?]()
    for dref in drefs {
        cDrefs.append(dref.cString(using: .utf8))
    }
    let result = getDREFs(&cDrefs, UInt8(drefs.count))
    return Int(result)
}

但是快速测试显示,如果使用多个字符串调用则不起作用。原因是当调用C函数时,dref.cString(using: .utf8)返回的数组已经被释放(并且指针无效)。

这是一个工作版本,对这个特殊情况略有修改Convert a Swift Array of String to a to a C string array pointer

public func get(drefs: [String]) -> Int {
    var cargs = drefs.map { UnsafePointer<Int8>(strdup($0)) }
    let result = getDREFs(&cargs, UInt8(drefs.count))
    for ptr in cargs { free(UnsafeMutablePointer(mutating: ptr)) }
    return Int(result)
}
© www.soinside.com 2019 - 2024. All rights reserved.