How to create UnsafeMutablePointer <UnsafeMutablePointer <UnsafeMutablePointer <Int8> >>
I work with the Swift C API and for one of the methods I need to call, I need to provide
UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>> Additional Information:
Swift Interface:
public func presage_predict(prsg: presage_t, _ result: UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>) -> presage_error_code_t Original C:
presage_error_code_t presage_predict(presage_t prsg, char*** result); As a rule, if the function accepts the UnsafePointer<T> parameter, then you can pass a variable of type T , as in the "inout" parameter, using & . In your case, T is
UnsafeMutablePointer<UnsafeMutablePointer<Int8>> being a Swift mapping of char ** . So you can call the function C a
var prediction : UnsafeMutablePointer<UnsafeMutablePointer<Int8>> = nil if presage_predict(prsg, &prediction) == PRESAGE_OK { ... } From the documentation and sample code of the Presage I library, understand that this allocates an array of strings and assigns the address of this array to the variable pointed to by prediction . To avoid memory leaks, these lines should be released eventually with
presage_free_string_array(prediction) To demonstrate that this really works, I took the first part of the demo code at presage_c_demo.c and translated it to Swift:
// Duplicate the C strings to avoid premature deallocation: let past = strdup("did you not sa") let future = strdup("") func get_past_stream(arg: UnsafeMutablePointer<Void>) -> UnsafePointer<Int8> { return UnsafePointer(past) } func get_future_stream(arg: UnsafeMutablePointer<Void>) -> UnsafePointer<Int8> { return UnsafePointer(future) } var prsg = presage_t() presage_new(get_past_stream, nil, get_future_stream, nil, &prsg) var prediction : UnsafeMutablePointer<UnsafeMutablePointer<Int8>> = nil if presage_predict(prsg, &prediction) == PRESAGE_OK { for var i = 0; prediction[i] != nil; i++ { // Convert C string to Swift `String`: let pred = String.fromCString(prediction[i])! print ("prediction[\(i)]: \(pred)") } presage_free_string_array(prediction) } free(past) free(future) It really worked and produced a way out.
prediction [0]: say prediction [1]: said prediction [2]: savages prediction [3]: saw prediction [4]: ββsat prediction [5]: same
There may be a better way, but this is done on the playground and determines the value of r with the type you want:
func ptrFromAddress<T>(p:UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T> { return p } var myInt:Int8 = 0 var p = ptrFromAddress(&myInt) var q = ptrFromAddress(&p) var r = ptrFromAddress(&q) What is the ptrFromAddress definition point that seems to be doing nothing? My thinking is that in the Swift interop section of the book, which discusses volatile pointers, there are many ways to initialize them by passing some expression as an argument (like &x ), but it doesn't seem to show the appropriate ways that you just call UnsafeMutablePointer initializer. Therefore, let's define the no-op function only to use these special initialization methods based on passing arguments
Update:
While I believe the above method is correct, another @alisoftware forum pointed out that this is apparently a safer and more idiomatic way to do the same:
var myInt: Int8 = 0 withUnsafeMutablePointer(&myInt) { (var p) in withUnsafeMutablePointer(&p) { (var pp) in withUnsafeMutablePointer(&pp) { (var ppp) in // Do stuff with ppp which is a UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>> } } } This is more idiomatic because you are using the withUnsafeMutablePointer function, which is provided by the standard Swift library, instead of defining your own helper. This is safer because you are guaranteed that UnsafeMutablePointer is only alive when the call closes (until the closure itself has a pointer).