Because the problem of getopt_long(3) is in the option.name lifetime (if more preciously, the content of buffer pointed by implicit String -> const char* conversion), I managed getopt_long() to work using StaticString with explicit conversion to UnsafePointer<CChar> (which is Swift counterpart of the const char*).
Something like that:
func newCCharPtrFromStaticString(_ str: StaticString) -> UnsafePointer<CChar>
{
let rp = UnsafeRawPointer(str.utf8Start);
let rplen = str.utf8CodeUnitCount;
return rp.bindMemory(to: CChar.self, capacity: rplen);
}
func main() -> Int32
{
enum OptLongCases: Int32 {
case h = 0x68;
case f = 0x66;
case OPT_FIRST = 256;
case version;
};
let longopts: [option] = [
option(name: newCCharPtrFromStaticString("help"), has_arg: no_argument, flag: nil, val: OptLongCases.h.rawValue),
option(name: newCCharPtrFromStaticString("version"), has_arg: no_argument, flag: nil, val: OptLongCases.version.rawValue),
option(name: newCCharPtrFromStaticString("file"), has_arg: required_argument, flag: nil, val: OptLongCases.f.rawValue /* Int32("f".utf8.first!) */),
option() // { NULL, NULL, NULL, NULL }
];
var hash: Dictionary<String, String> = [:];
while (true)
{
let opt = getopt_long(CommandLine.argc, CommandLine.unsafeArgv, "hf:", longopts, nil);
switch (opt)
{
case OptLongCases.h.rawValue:
Help();
return EXIT_SUCCESS;
case OptLongCases.version.rawValue:
Version();
return EXIT_SUCCESS;
case OptLongCases.f.rawValue:
hash["f"] = String(cString: optarg);
case 0: // long option with non-NULL .flag field, the value returned there
break;
case -1: // end of options
break;
default:
UseHelp();
return EXIT_FAILURE;
}
if (opt == -1)
{
break;
}
}
if let fn = hash["f"] {
print("-f aka --file = \"\(fn)");
}
for u in optind ..< CommandLine.argc {
let i = Int(u);
let s = CommandLine.arguments[i];
print("argv[\(i)] = \"\(s)\"");
}
return EXIT_SUCCESS;
}