Last active
August 10, 2019 09:11
-
-
Save yangyubo/a9d681f29df3a1a2cab065a0b1b41731 to your computer and use it in GitHub Desktop.
Passing an Array of Strings from Swift to C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Support for array of C strings | |
// https://oleb.net/blog/2016/10/swift-array-of-c-strings/ | |
// https://github.com/apple/swift/blob/master/stdlib/private/SwiftPrivate/SwiftPrivate.swift | |
private func scan< | |
S : Sequence, U | |
>(_ seq: S, _ initial: U, _ combine: (U, S.Iterator.Element) -> U) -> [U] { | |
var result: [U] = [] | |
result.reserveCapacity(seq.underestimatedCount) | |
var runningResult = initial | |
for element in seq { | |
runningResult = combine(runningResult, element) | |
result.append(runningResult) | |
} | |
return result | |
} | |
func withArrayOfCStrings<R>( | |
_ args: [String], _ body: ([UnsafeMutablePointer<CChar>?]) -> R | |
) -> R { | |
let argsCounts = Array(args.map { $0.utf8.count + 1 }) | |
let argsOffsets = [ 0 ] + scan(argsCounts, 0, +) | |
let argsBufferSize = argsOffsets.last! | |
var argsBuffer: [UInt8] = [] | |
argsBuffer.reserveCapacity(argsBufferSize) | |
for arg in args { | |
argsBuffer.append(contentsOf: arg.utf8) | |
argsBuffer.append(0) | |
} | |
return argsBuffer.withUnsafeMutableBufferPointer { | |
(argsBuffer) in | |
let ptr = UnsafeMutableRawPointer(argsBuffer.baseAddress!).bindMemory( | |
to: CChar.self, capacity: argsBuffer.count) | |
var cStrings: [UnsafeMutablePointer<CChar>?] = argsOffsets.map { ptr + $0 } | |
cStrings[cStrings.count - 1] = nil | |
return body(cStrings) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment