Search code examples
cswift3swift2unsafemutablepointer

swift3.0 Cannot convert value of type '[UnsafeMutablePointer<Int8>]' to expected argument type 'UnsafeMutablePointer<Int8>?'


This code worked well in Swift2.3 and now I am converting it to Swift3. So I am getting this error. Anyone has idea, how to fix this?

var cmdLnConf: OpaquePointer?
fileprivate var cArgs: [UnsafeMutablePointer<Int8>]

public init?(args: (String,String)...) {

    // Create [UnsafeMutablePointer<Int8>].
    cArgs = args.flatMap { (name, value) -> [UnsafeMutablePointer<Int8>] in
        //strdup move the strings to the heap and return a UnsageMutablePointer<Int8>
        return [strdup(name),strdup(value)]
    }

    cmdLnConf = cmd_ln_parse_r(nil, ps_args(), CInt(cArgs.count), &cArgs, STrue)

    if cmdLnConf == nil {
        return nil
    }
}

enter image description here


Solution

  • based on our discussion it seems that parameter in your C function should be char *p[]

    I made a small test

    //
    //  f.h
    //  test001
    //
    
    #ifndef f_h
    #define f_h
    
    #include <stdio.h>
    
    void f(char *p[], int len);
    
    #endif /* f_h */
    

    I defined the function with some basic functionality

    //
    //  f.c
    //  test001
    
    #include "f.h"
    
    void f(char *p[], int len) {
        for(int i = 0; i<len; i++) {
            printf("%s\n", p[i]);
        };
    
    };
    

    with the required bridging header

    //
    //  Use this file to import your target's public headers that you would like to expose to Swift.
    //
    
    #include "f.h"
    

    and swift 'command line' application

    //
    //  main.swift
    //  test001
    //
    
    import Darwin
    
    var s0 = strdup("alfa")
    var s1 = strdup("beta")
    var s2 = strdup("gama")
    var s3 = strdup("delta")
    
    
    var arr = [s0,s1,s2,s3]
    let ac = Int32(arr.count)
    
    
    arr.withUnsafeMutableBytes { (p) -> () in
        let pp = p.baseAddress?.assumingMemoryBound(to: UnsafeMutablePointer<Int8>?.self)
        f(pp, ac)
    }
    

    it finally prints

    alfa
    beta
    gama
    delta
    Program ended with exit code: 0
    

    based on the result, your have to use

    let count = CInt(cArgs.count)
    cArgs.withUnsafeMutableBytes { (p) -> () in
        let pp = p.baseAddress?.assumingMemoryBound(to: UnsafeMutablePointer<Int8>?.self)  
        cmdLnConf = cmd_ln_parse_r(nil, ps_args(), count, pp, STrue)
    }
    

    WARNING!!! don't call cArgs.count inside the closure, where the pointer is defined!