1

I'm calling a C library from Swift 4 and I have troubles converting a [String] to const char *[].

The C API defines this method:

int getDREFs(const char* drefs[], unsigned char count);

which is exposed in Swift as

public func getDREFs(_ drefs: UnsafeMutablePointer<UnsafePointer<Int8>?>!, _ count: UInt8) -> Int32

The Swift wrapper I'm trying to write is the following

public func get(drefs: [String]) throws {

    var cDrefs = [UnsafePointer<Int8>]()
    for dref in drefs {
        cDrefs.append(dref.cString(using: .utf8)!)
    }
    let pDrefs = UnsafeMutablePointer<UnsafePointer<Int8>>(&cDrefs)
    getDREFFs(pDrefs, drefs.count)

}

but the error I get is

Cannot convert value of type 'UnsafeMutablePointer<UnsafePointer<Int8>>' to expected argument type 'UnsafeMutablePointer<UnsafePointer<Int8>?>!'

what am I missing?

2
  • Any feedback on the answer? Please let me know if you need more information. Commented Jan 5, 2018 at 10:15
  • yes sorry, I forgot to accept your answer Commented Jan 5, 2018 at 10:25

1 Answer 1

2

getDREFSs expects a pointer to an array of optional Int8 pointers. Also the second argument must be converted to UInt8.

So this would compile:

public func get(drefs: [String]) -> Int {
    var cDrefs = [UnsafePointer<Int8>?]()
    for dref in drefs {
        cDrefs.append(dref.cString(using: .utf8))
    }
    let result = getDREFs(&cDrefs, UInt8(drefs.count))
    return Int(result)
}

But a quick test shows that is does not work if called with multiple strings. The reason is that the arrays returned by dref.cString(using: .utf8) can already be deallocated (and the pointer invalid) when the C function is called.

Here is a working version, a slight modification of Convert a Swift Array of String to a to a C string array pointer for this particular case:

public func get(drefs: [String]) -> Int {
    var cargs = drefs.map { UnsafePointer<Int8>(strdup($0)) }
    let result = getDREFs(&cargs, UInt8(drefs.count))
    for ptr in cargs { free(UnsafeMutablePointer(mutating: ptr)) }
    return Int(result)
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.