How to I access argv and argc in swift?
There are two ways to do this:
- The constants
C_ARGC
andC_ARGV
. They are analogous to theargc
andargv
you'd see in amain()
function. - The
CommandLine.arguments
array will contain all of the arguments to the process. (In Swift 2,CommandLine
was calledProcess
)
How do I access program arguments in Swift?
Process was just renamed into CommandLine (since Swift 3.0 August 4 snapshot)
let arguments = CommandLine.arguments
(for some reason this wasn't mentioned on the changelog)
Swift C interop: Passing Swift Argv to C argv
Try the following (tested with Xcode 12 / swift 5.3)
let values: UnsafePointer<UnsafePointer<Int8>?> =
UnsafeRawPointer(CommandLine.unsafeArgv).bindMemory(
to: UnsafePointer<Int8>?.self,
capacity: Int(CommandLine.argc)
)
your_api_func(Int(CommandLine.argc), values)
Alternate: (on @MartinR comment) tested & worked as well.
CommandLine.unsafeArgv.withMemoryRebound(
to: UnsafePointer<Int8>?.self,
capacity: Int(CommandLine.argc)) { ptr in
your_api_func(Int(CommandLine.argc), ptr)
}
How do you access command line arguments in Swift?
Apple has released the ArgumentParser
library for doing just this:
We’re delighted to announce
ArgumentParser
, a new open-source library that makes it straightforward — even enjoyable! — to parse command-line arguments in Swift.https://swift.org/blog/argument-parser/
Swift Argument Parser
https://github.com/apple/swift-argument-parser
Begin by declaring a type that defines the information you need to collect from the command line. Decorate each stored property with one of
ArgumentParser
's property wrappers, and declare conformance toParsableCommand
.The
ArgumentParser
library parses the command-line arguments, instantiates your command type, and then either executes your customrun()
method or exits with useful a message.
How to decleare char *const argv[] in swift
The easy way is to let Cocoa form the C strings for you:
let args = ["/usr/bin/printf","BBB"]
var cs = UnsafeMutablePointer<UnsafeMutablePointer<Int8>>.alloc(2)
for (ix,s) in args.enumerate() {
cs[ix] = UnsafeMutablePointer<Int8>((s as NSString).UTF8String)
}
var cs2 : UnsafePointer<UnsafeMutablePointer<Int8>> = UnsafePointer(cs)
Beware; cs
does not contain copies. Its pointers are pointing right into the strings in args
.
How to get arguments of NSRunningApplication?
The "ps" tool uses sysctl()
with KERN_PROCARGS2
to get the arguments of a running process. The following is an attempt to translate the code from adv_cmds-153/ps/print.c to Swift. That file also contains a documentation of the memory layout of the raw argument space and explains how to locate the string arguments in that memory.
func processArguments(pid: pid_t) -> [String]? {
// Determine space for arguments:
var name : [CInt] = [ CTL_KERN, KERN_PROCARGS2, pid ]
var length: size_t = 0
if sysctl(&name, CUnsignedInt(name.count), nil, &length, nil, 0) == -1 {
return nil
}
// Get raw arguments:
var buffer = [CChar](repeating: 0, count: length)
if sysctl(&name, CUnsignedInt(name.count), &buffer, &length, nil, 0) == -1 {
return nil
}
// There should be at least the space for the argument count:
var argc : CInt = 0
if length < MemoryLayout.size(ofValue: argc) {
return nil
}
var argv: [String] = []
buffer.withUnsafeBufferPointer { bp in
// Get argc:
memcpy(&argc, bp.baseAddress, MemoryLayout.size(ofValue: argc))
var pos = MemoryLayout.size(ofValue: argc)
// Skip the saved exec_path.
while pos < bp.count && bp[pos] != 0 {
pos += 1
}
if pos == bp.count {
return
}
// Skip trailing '\0' characters.
while pos < bp.count && bp[pos] == 0 {
pos += 1
}
if pos == bp.count {
return
}
// Iterate through the '\0'-terminated strings.
for _ in 0..<argc {
let start = bp.baseAddress! + pos
while pos < bp.count && bp[pos] != 0 {
pos += 1
}
if pos == bp.count {
return
}
argv.append(String(cString: start))
pos += 1
}
}
return argv.count == argc ? argv : nil
}
There is only a simple error handling: if anything goes wrong, the function returns nil
.
For an instance of NSRunningApplication
you can then call
processArguments(pid: application.processIdentifier)
How can I use getopt with command line arguments in Swift 3?
@Hamish already answered the question and explained how to pass CommandLine.unsafeArgv
to getopt()
in Swift (and why).
Here is a complete self-contained example how a typical getopt
loop can be implemented in Swift 3:
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 ?? "?")
Remarks:
- You can pass a Swift string (here:
"abc:"
) directly to a C
function expecting a (constant) C string, the compiler will automatically
generate a temporary UTF-8 representation. getopt()
return either-1
(if the argument list is exhausted) or anunsigned char
converted to anint
. Therefore it is safe to
convert the return value toCUnsignedChar
(which isUInt8
in Swift).while
is used (abused?) with pattern matching plus an additional
boolean condition to implement the typical C patternwhile ((option = getopt(argc, argv, "abc:")) != -1) { ... }
in Swift.
Related Topics
Using Custom Cifilter on Calayer Shows No Change to Calayer
How to Grant Discoveruserinfowithuserrecordid Permission
Create Spotlight-Like Window in Swift 4
How to Replace Limited Number of Occurrences in String
Ios/Tvos Playground Fails with "Unable to Find Execution Service for Selected Run Destination"
Nsdateformatter Detect 24-Hour Clock in Os X and iOS
How to Create an Uppercase Version of a String in Swiftui
Swift: Overriding Typealias Inside Subclass
From the Swift Repl, How to Get a List of Available Modules
Is Dispatchsemaphore a Good Replacement for Nslock
Swiftui: Navigationlink Not Working If Not in a List
Spritekit Particle Emitter Multi Image
What Does "Constrain to Margins" Mean in Interface Builder in Xcode 6.0.1
How to Immediately See Swift Errors in Appcode
In What Situation Would One Use Expectationfornotification in Swift Testing