如何将 Swift 字符串数组传递给采用 char ** 参数的 C 函数
How to pass an array of Swift strings to a C function taking a char ** parameter
我正在尝试与来自 Swift 的旧 C 终端应用程序进行交互。我已经成功地集成了源代码并将 headers 从 C 桥接到 Swift。代码从 Xcode 6.3 beta 编译并运行。我已将终端应用程序的主要入口点重命名为:
int initialize(int argc, char **argv);
尽管如此,我正在努力将参数从 Swift 传递给此 C 函数。我的挑战是以正确的格式转换参数。来自 Swift 的典型输入如下所示:
let args = ["-c", "1.2.3.4", "-p", "8000"]
我试过弄乱 "cStringUsingEncoding(NSUTF8StringEncoding)" 和 "withUnsafePointer",但到目前为止运气不好。非常感谢任何帮助!
C函数
int initialize(int argc, char **argv);
映射到 Swift 为
func initialize(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32
这是一个可能的解决方案:
let args = ["-c", "1.2.3.4", "-p", "8000"]
// Create [UnsafeMutablePointer<Int8>]:
var cargs = args.map { strdup([=12=]) }
// Call C function:
let result = initialize(Int32(args.count), &cargs)
// Free the duplicated strings:
for ptr in cargs { free(ptr) }
它利用了 strdup([=13=])
Swift 字符串 [=14=]
自动转换为 C 字符串,
如 String value to UnsafePointer<UInt8> function parameter behavior.
中所述
根据 Martin 的回答,如果你发现自己经常这样做,你可以将 dup/free 部分包装成一个类似于 String.withCString
:
的函数
import Darwin
func withCStrings
<R, S: SequenceType where S.Generator.Element == String>
(strings: S, @noescape body: (UnsafeBufferPointer<UnsafeMutablePointer<Int8>>) -> R)
-> R {
let cstrings = map(strings) { strdup([=10=]) } + [nil]
let result = cstrings.withUnsafeBufferPointer(body)
for ptr in cstrings { free(ptr) }
return result
}
let execvargs = ["/usr/bin/say"] + dropFirst(Process.arguments)
let execvresult = withCStrings(execvargs) {
execv([=10=][0], [=10=].baseAddress)
}
我正在尝试与来自 Swift 的旧 C 终端应用程序进行交互。我已经成功地集成了源代码并将 headers 从 C 桥接到 Swift。代码从 Xcode 6.3 beta 编译并运行。我已将终端应用程序的主要入口点重命名为:
int initialize(int argc, char **argv);
尽管如此,我正在努力将参数从 Swift 传递给此 C 函数。我的挑战是以正确的格式转换参数。来自 Swift 的典型输入如下所示:
let args = ["-c", "1.2.3.4", "-p", "8000"]
我试过弄乱 "cStringUsingEncoding(NSUTF8StringEncoding)" 和 "withUnsafePointer",但到目前为止运气不好。非常感谢任何帮助!
C函数
int initialize(int argc, char **argv);
映射到 Swift 为
func initialize(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32
这是一个可能的解决方案:
let args = ["-c", "1.2.3.4", "-p", "8000"]
// Create [UnsafeMutablePointer<Int8>]:
var cargs = args.map { strdup([=12=]) }
// Call C function:
let result = initialize(Int32(args.count), &cargs)
// Free the duplicated strings:
for ptr in cargs { free(ptr) }
它利用了 strdup([=13=])
Swift 字符串 [=14=]
自动转换为 C 字符串,
如 String value to UnsafePointer<UInt8> function parameter behavior.
根据 Martin 的回答,如果你发现自己经常这样做,你可以将 dup/free 部分包装成一个类似于 String.withCString
:
import Darwin
func withCStrings
<R, S: SequenceType where S.Generator.Element == String>
(strings: S, @noescape body: (UnsafeBufferPointer<UnsafeMutablePointer<Int8>>) -> R)
-> R {
let cstrings = map(strings) { strdup([=10=]) } + [nil]
let result = cstrings.withUnsafeBufferPointer(body)
for ptr in cstrings { free(ptr) }
return result
}
let execvargs = ["/usr/bin/say"] + dropFirst(Process.arguments)
let execvresult = withCStrings(execvargs) {
execv([=10=][0], [=10=].baseAddress)
}