Search code examples
cswiftlanguage-interoperability

How to pass an array of Swift strings to a C function taking a char ** parameter


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:

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:

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!


Solution

  • The C function

    int initialize(int argc, char **argv);
    

    is mapped to 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.