Swift字符串数组到const char * const *

时间:2016-04-22 02:31:27

标签: c swift

我无法将Swift字符串数组转换为带有签名的c函数的数组:

PGconn *PQconnectStartParams(const char * const *keywords, const char * const *values, int expand_dbname)

在Swift中, const char * const * 显示为:

<UnsafePointer<UnsafePointer<Int8>>

所以我尝试转换一个名为'options'的Dictionary [String:String]的内容,并将其提供给函数,如下所示:

var keys = [[Int8]]()
var values = [[Int8]]()
for (key, value) in options {
    var int8Array = key.cStringUsingEncoding(NSUTF8StringEncoding)!
    keys.append(int8Array)
    int8Array = value.cStringUsingEncoding(NSUTF8StringEncoding)!
            values.append(int8Array)
}
pgConnection = PQconnectStartParams(UnsafePointer(keys), UnsafePointer(values), 0)

它编译并运行,但该功能不起作用。

非常感谢任何见解。

2 个答案:

答案 0 :(得分:3)

这不完美,但至少它有效。

let options = ["key1": "value1", "key2": "value2", "key3": "value3", "key4": "value4"]

var keys = [String]()

for (key, value) in options {

    keys.append(key)
}

//you need to identify how many paramenters should be provided and set them following "static way"
//I did not find how to prepare this dynamically
let cKey1 = keys[0].cStringUsingEncoding(String.defaultCStringEncoding())!
let key1Pointer = UnsafePointer<CChar>(cKey1)

let cKey2 = keys[1].cStringUsingEncoding(String.defaultCStringEncoding())!
let key2Pointer = UnsafePointer<CChar>(cKey2)

let cKey3 = keys[2].cStringUsingEncoding(String.defaultCStringEncoding())!
let key3Pointer = UnsafePointer<CChar>(cKey3)

let cKey4 = keys[3].cStringUsingEncoding(String.defaultCStringEncoding())!
let key4Pointer = UnsafePointer<CChar>(cKey4)


let keysCArray = [key1Pointer, key2Pointer, key3Pointer, key4Pointer]

f(keysCArray)

/*
 C - code

 void f(const char * const *keywords) {

 printf("%s\n", keywords[0]);
 printf("%s\n", keywords[1]);
 printf("%s\n", keywords[2]);
 printf("%s\n", keywords[3]);

 }
 */

希望它有所帮助。如果你愿意,我可以分享我的示例应用程序。

答案 1 :(得分:0)

这是Swift3中Array的扩展,通常会这样做:

<div class="container">
   a: <input type="text" maxlength="5" />
   b: <input type="text" maxlength="5" />
   c: <input type="text" maxlength="5" />
</div>
<script>
   var container = document.getElementsByClassName("container")[0];
   container.onkeyup = function(e) {
       var target = e.target;
       var maxLength = parseInt(target.attributes["maxlength"].value, 10);
       var myLength = target.value.length;
       if (myLength >= maxLength) {
          var next = target;
          while (next = next.nextElementSibling) {
              if (next == null)
                  break;
              if (next.tagName.toLowerCase() == "input") {
                  next.focus();
                  break;
              }
          }
      }
  }
</script>

然后你可以通过

获得正确的C兼容指针
public extension Array {

    // Translate [String] to (const char * const *), which translates to Swift as
    public func cStringArray() throws -> ArrayBridge<Element,CChar> {
        return try ArrayBridge<Element,CChar>(array:self) {
            guard let item = $0 as? String,
                  let translated = item.cString(using: .utf8) else {
                fatalError()
            }
            return translated
        }
    }
}

/*
 We need to have this intermediate object around to hold on to the translated objects, otherwise they will go away.
 The UnsafePointer won't hold on to the objects that it's pointing to.
 */
public struct ArrayBridge<SwiftType,CType> {

    let originals  :[SwiftType]
    let translated :[[CType]]
    let pointers   :[UnsafePointer<CType>?]
    public let pointer    :UnsafePointer<UnsafePointer<CType>?>

    init(array :[SwiftType], transform: @noescape (SwiftType) throws -> [CType]) throws {
        self.originals = array
        self.translated = try array.map(transform)

        var pointers = [UnsafePointer<CType>?]()
        for item in translated {
            pointers.append(UnsafePointer<CType>(item))
        }
        pointers.append(nil)
        self.pointers = pointers
        self.pointer = UnsafePointer(self.pointers)
    }
}