Reputation: 1779
The C function I wish to call is documented as:
GDALVectorTranslateOptions* GDALVectorTranslateOptionsNew(char** papszArgv, GDALVectorTranslateOptionsForBinary* psOptionsForBinary)
...and is imported to swift as:
public func GDALVectorTranslateOptionsNew(_ papszArgv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>!, _ psOptionsForBinary: OpaquePointer!) -> OpaquePointer!
I have been unable to convert my swift array of strings into a C array of C strings in such a way that does not produce an error.
I have tried various methods found during research, and they all end up with similar errors being produced. My current method is to use the following function to convert the Swift array of strings to be used within a closure:
public func withArrayOfCStrings<R>(_ args: [String], _ body: ([UnsafeMutablePointer<CChar>?]) -> R) -> R {
var cStrings = args.map { strdup($0) }
cStrings.append(nil)
defer {
cStrings.forEach { free($0) }
}
return body(cStrings)
}
I'm attempting to use it all like this:
var opts = ["blah1", "blah2"]
withArrayOfCStrings(opts) { (cOpts) in
let translateOpts = GDALVectorTranslateOptionsNew(cOpts, nil)
}
But I get the error:
Cannot convert value of type '[UnsafeMutablePointer?]' (aka 'Array<Optional<UnsafeMutablePointer>>') to expected argument type 'UnsafeMutablePointer<UnsafeMutablePointer?>?'
How should I be doing this?
Upvotes: 1
Views: 165
Reputation: 539685
That withArrayOfCStrings
function works with C functions taking a char * const *
argument, i.e. a pointer to constant pointers to characters.
If you change the C declaration to
GDALVectorTranslateOptions* GDALVectorTranslateOptionsNew(char* const* papszArgv,
GDALVectorTranslateOptionsForBinary* psOptionsForBinary)
then it compiles and runs as expected.
If you do not have the option to modify the C code then you can change the helper method to
public func withArrayOfCStrings<R>(_ args: [String],
_ body: (UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>) -> R) -> R {
var cStrings = args.map { strdup($0) }
cStrings.append(nil)
defer {
cStrings.forEach { free($0) }
}
return body(&cStrings)
}
The body is now called with a UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>
argument, which corresponds to a C char **
argument.
Upvotes: 1