Swift 3:将字符串数组转换为C字符数组的编译错误

时间:2016-09-01 11:07:16

标签: c arrays swift xcode8

我有以下C结构:

typedef struct {
  char** categories;
  int category_size;
} category_fmc_s_type;

My Swift数组具有以下值:

let categories = ["Weekday", "Weekend"]

我想填充C Struct字段'类别'与工作日' &安培; '周末&#39 ;.要做到这一点,我调用我的toPointer():

fileprivate static func toPointer(_ args: [String]) -> UnsafeMutablePointer<UnsafeMutablePointer<Int8>> {
  let buffer = UnsafeMutablePointer<UnsafeMutablePointer<Int8>>.allocate(capacity: args.count)
  for (index, value) in args.enumerated() {
    buffer[index] = UnsafeMutablePointer<Int8>(mutating: (value as NSString).utf8String!)
  }
  return buffer
}

我一直收到以下XCode 8错误:

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

有什么建议吗?我不明白为什么有可选的&#39;!&#39;在隐含的C-Struct定义中。

2 个答案:

答案 0 :(得分:0)

由于编译器发出错误,您需要在 Int8 w /“”之后展开,如下所示。

fileprivate func toPointer(_ args: [String]) -> UnsafeMutablePointer<UnsafeMutablePointer<Int8>?> {
  let buffer = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: args.count)
  for (index, value) in args.enumerated() {
    buffer[index] = UnsafeMutablePointer<Int8>(mutating: (value as NSString).utf8String!)
  }
  return buffer
}

然后,

func testMyCat() {
  let categories = ["Weekday", "Weekend"]
  let buffer = toPointer(categories)
  var mycat = category_fmc_s_type()
  mycat.categories = buffer  // you would see compile error w/o "?"
}

上面的代码没有错误。 Martin's solution

处出现编译错误

mycat.categories =&amp; cargs(见链接)

我不知道为什么。

答案 1 :(得分:0)

检查reference of utf8String property of NSString

  

讨论

     

此C字符串是指向字符串对象内部结构的指针,   它的寿命可能比字符串对象短,并且会   肯定没有更长的寿命。因此,你应该复制   C字符串,如果它需要存储在内存上下文中   你使用这个属性。

术语内存上下文没有明确定义,但有一点可以肯定的是,您不能指望C字符串的已分配区域将永远存在。访问categories中的成员category_fmc_s_type时,指针可能指向已经释放的区域。

将Martin R的建议应用到您的代码中,您的代码将是这样的:

fileprivate static func toPointer(_ args: [String]) -> UnsafeMutablePointer<UnsafeMutablePointer<Int8>?> {
    let buffer = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: args.count)
    buffer.initialize(from: args.lazy.map{strdup($0)})
    return buffer
}

请记住,在使用category_fmc_s_type后,您需要释放由strdup(_:)UnsafeMutablePointer.allocate(capacity:)分配的区域:

fileprivate static func freePointer(_ pointers: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>, count: Int) {
    for i in 0..<count {
        free(pointers[i])
    }
    pointers.deinitialize(count: count)
    pointers.deallocate(capacity: count)
}