简体   繁体   English

Swift 3:将String Array转换为C Char Array的编译错误

[英]Swift 3: Compilation error converting String Array to C Char Array

I have the following C struct: 我有以下C结构:

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

My Swift array has the following values: 我的Swift数组具有以下值:

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

I want to populate the C Struct field 'categories' with 'Weekday' & 'Weekend'. 我想用'Weekday'和'Weekend'填充C Struct字段'categories'。 To do this I call my toPointer(): 要做到这一点,我调用我的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
}

I keep getting the following XCode 8 error: 我一直收到以下XCode 8错误:

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

Any suggestions? 有什么建议么? I don't understand why there is the optional and '!' 我不明白为什么有可选和'!' in the C-Struct definition implicitly. 隐含地在C-Struct定义中。

As the compiler emits as an error, you need to unwrap after Int8 w/ " ? " as follows. 当编译器作为错误发出时,你需要在Int8之后 ”解开,如下所示。

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
}

then, 然后,

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 "?"
}

the code above works w/o error. 上面的代码没有错误。 Martin's solution gives a compile error at Martin的解决方案给出了编译错误

mycat.categories = &cargs (see the link) mycat.categories =&cargs(见链接)

I don't know why. 我不知道为什么。

Check the reference of utf8String property of NSString : 检查NSStringutf8String属性引用

Discussion 讨论

This C string is a pointer to a structure inside the string object, which may have a lifetime shorter than the string object and will certainly not have a longer lifetime. 此C字符串是指向字符串对象内部结构的指针,该结构的生命周期可能短于字符串对象,并且肯定不会有更长的生命周期。 Therefore, you should copy the C string if it needs to be stored outside of the memory context in which you use this property. 因此, 如果需要将C字符串存储在使用此属性的内存上下文之外,则应将其复制

The term memory context is not well-defined, but one thing sure is that you cannot expect the allocated region for the C string would live forever. 术语内存上下文没有明确定义,但有一点可以肯定的是,您不能指望C字符串的已分配区域将永远存在。 When the member categories in the category_fmc_s_type is accessed, the pointers may be pointing to the already freed regions. 当访问category_fmc_s_type的成员categories时,指针可以指向已经释放的区域。

Applying the suggestion from Martin R to your code, your code would be like this: 将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
}

And remember, after you finish using the category_fmc_s_type , you need to deallocate the regions allocated by strdup(_:) and UnsafeMutablePointer.allocate(capacity:) : 请记住,在使用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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM