如何在Swift 3中使用带有命令行参数的getopt?

Dri*_*ler 3 command-line swift swift3

我正在尝试在Swift 3中使用带有命令行参数的getopt.我有来自Michele Dall'Agata的很好的stackoverflow贡献:

let pattern = "abc:"
var buffer = Array( pattern.utf8 ).map { Int8($0) }
Run Code Online (Sandbox Code Playgroud)

当我然后使用此代码时:

let option = Int( getopt( CommandLine.argc, CommandLine.arguments, buffer ) )
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

无法将'[String]'类型的值转换为预期的参数类型'UnsafePointer <UnsafeMutablePointer <Int8>?>!'

对于我正在尝试使用的CommandLine.arguments argv.有谁知道第二个参数的正确语法getopt?提前致谢!

Mar*_*n R 7

@Hamish已经回答了这个问题并解释了如何传递CommandLine.unsafeArgvgetopt()Swift(以及为什么).

这是一个完整的自包含示例,如何在Swift 3中实现典型的getopt循环:

var aFlag = false
var bFlag = false
var cValue: String?

while case let option = getopt(CommandLine.argc, CommandLine.unsafeArgv, "abc:"), option != -1 {
    switch UnicodeScalar(CUnsignedChar(option)) {
    case "a":
        aFlag = true
    case "b":
        bFlag = true
    case "c":
        cValue = String(cString: optarg)
    default:
        fatalError("Unknown option")
    }
}

print(aFlag, bFlag, cValue ?? "?")
Run Code Online (Sandbox Code Playgroud)

备注:

  • 您可以将Swift字符串(此处:) "abc:"直接传递给期望(常量)C字符串的C函数,编译器将自动生成临时UTF-8表示.
  • getopt()返回-1(如果参数列表已用尽)或unsigned char转换为int.因此,将返回值转换为CUnsignedChar(UInt8在Swift中)是安全的.
  • while 使用(滥用?)模式匹配加上一个额外的布尔条件来实现典型的C模式

    while ((option = getopt(argc, argv, "abc:")) != -1) { ... }
    
    Run Code Online (Sandbox Code Playgroud)

    在斯威夫特.


Ham*_*ish 5

CommandLine.arguments给你一个友好的Swift [String]传递的参数 - 但是你想要将参数直接发送回C.因此你可以简单地使用CommandLine.unsafeArgv,它将为你提供argv传递给你的程序的实际原始值.

let option = Int( getopt( CommandLine.argc, CommandLine.unsafeArgv, buffer ) )
Run Code Online (Sandbox Code Playgroud)