如何将一个由Swift字符串组成的数组传递给一个接受char **参数的C函数

11

我正在尝试从Swift与一个旧的C终端应用程序进行交互。我已经成功地将C语言代码集成到Swift中,并且从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函数调用中的char **参数,可以更好地解决问题。 - Wizard of Kneup
2个回答

16

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($0) }
// Call C function:
let result = initialize(Int32(args.count), &cargs)
// Free the duplicated strings:
for ptr in cargs { free(ptr) }

它利用了在strdup($0)中,Swift字符串$0会自动转换为C字符串的事实, 正如在String value to UnsafePointer<UInt8> function parameter behavior中所解释的那样。


谢谢,运行得很好。对于其他试图做类似事情的人,我应该补充说明C从索引1开始传递参数向量而不是0。我更新了我的参数为:let args = ["", "-c", "1.2.3.4", "-p", "8000"]。 - Mark
如果我有一个命令行游戏,你觉得能否在Swift中运行它并传递参数,并将其stdout提取到文本区域中?或者我必须从头开始使用它的函数来制作游戏?@Mark - MasterWizard
@AhmedNassar:据我所知,在iOS上无法运行外部程序。 - Martin R
不是外部的,我在我的项目中有C程序,我能把参数传递给它的主函数吗? - MasterWizard
@AhmedNassar:使用上述方法应该是可行的。您可能需要重命名主函数。 - Martin R
但是我不想一次性传递所有参数,因为我正在等待stdout,我该怎么做?如果我问了很多愚蠢的问题,对不起,我在C方面没有经验。 - MasterWizard

1
在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)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接