I'm trying to interact with an old C terminal app from Swift. I've successfully integrated the source code and bridged the headers from C to Swift. The code compiles and runs from Xcode 6.3 beta. I've renamed the terminal app's main entry point to:
我正在尝试与Swift的旧C终端应用程序进行交互。我已成功集成源代码并将标头从C桥接到Swift。该代码从Xcode 6.3 beta编译并运行。我已将终端应用程序的主要入口点重命名为:
int initialize(int argc, char **argv);
Nevertheless, I'm struggling to pass the arguments from Swift to this C function. My challenge is to convert the arguments in the right format. Typical input from Swift would look like:
然而,我正在努力将Swift中的参数传递给这个C函数。我的挑战是以正确的格式转换参数。 Swift的典型输入看起来像:
let args = ["-c", "1.2.3.4", "-p", "8000"]
I've tried messing with "cStringUsingEncoding(NSUTF8StringEncoding)" and "withUnsafePointer", but no luck so far. Any help is greatly appreciated!
我已经尝试搞乱“cStringUsingEncoding(NSUTF8StringEncoding)”和“withUnsafePointer”,但到目前为止还没有运气。任何帮助是极大的赞赏!
2 个解决方案
#1
8
The C function
C函数
int initialize(int argc, char **argv);
is mapped to Swift as
映射到Swift as
func initialize(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32
This is a possible solution:
这是一个可能的解决方案:
let args = ["-c", "1.2.3.4", "-p", "8000"]
// Create [UnsafeMutablePointer<Int8>]:
var cargs = args.map { strdup($0) }
// Call C function:
let result = initialize(Int32(args.count), &cargs)
// Free the duplicated strings:
for ptr in cargs { free(ptr) }
It uses the fact that in strdup($0)
the Swift string $0
is automatically converted to a C string, as explained in String value to UnsafePointer<UInt8> function parameter behavior.
它使用strdup($ 0)中的事实,Swift字符串$ 0自动转换为C字符串,如字符串值到UnsafePointer
#2
0
Building on Martin’s answer, if you find yourself doing this a lot, you could wrap the dup/free part into a function in a similar style to String.withCString
:
基于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($0) } + [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($0[0], $0.baseAddress)
}
#1
8
The C function
C函数
int initialize(int argc, char **argv);
is mapped to Swift as
映射到Swift as
func initialize(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32
This is a possible solution:
这是一个可能的解决方案:
let args = ["-c", "1.2.3.4", "-p", "8000"]
// Create [UnsafeMutablePointer<Int8>]:
var cargs = args.map { strdup($0) }
// Call C function:
let result = initialize(Int32(args.count), &cargs)
// Free the duplicated strings:
for ptr in cargs { free(ptr) }
It uses the fact that in strdup($0)
the Swift string $0
is automatically converted to a C string, as explained in String value to UnsafePointer<UInt8> function parameter behavior.
它使用strdup($ 0)中的事实,Swift字符串$ 0自动转换为C字符串,如字符串值到UnsafePointer
#2
0
Building on Martin’s answer, if you find yourself doing this a lot, you could wrap the dup/free part into a function in a similar style to String.withCString
:
基于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($0) } + [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($0[0], $0.baseAddress)
}