I am trying to implement to write a wrapper around libssh2 using Swift. The following code is for removing a file via SFTP.
func removeFile(_ path: String) {
let data = path.data(using: String.Encoding.utf8)!
let result = data.withUnsafeBytes { (pointer: UnsafePointer<Int8>) -> Int in
return libssh2_sftp_unlink_ex(sftpHandle, pointer, data.count)
}
}
For pointer: UnsafePointer<Int8>
I am getting the following error message:
'UnsafePointer<Int8>' is not convertible to 'UnsafePointer<_>
I found this thread about a similar Problem with UInt8
. I tried removing the cast but was just getting the next error:
'Swift.UnsafePointer<_>' is not convertible to 'Swift.UnsafePointer<_>'
Running the libssh2_sftp_unlink_ex(sftpHandle, pointer, data.count)
outside the closure with a dummy pointer works.
I also found this answer on converting a String to UInt8
, the problem is that I wasn't able to port it to Int8
. Any ideas on how to correctly convert the pointer?
data.withUnsafeBytes
calls the closure with an UnsafeRawBufferPointer
, this has to be “bound” to an UnsafePointer<Int8>
. Also data.count
must be converted to an UInt32
(aka CUnsignedInt
) because that is how the C type unsigned integer
is imported to Swift:
func removeFile(_ path: String) {
let data = path.data(using: String.Encoding.utf8)!
let result = data.withUnsafeBytes {
libssh2_sftp_unlink_ex(sftpHandle,
$0.bindMemory(to: Int8.self).baseAddress,
UInt32(data.count))
}
}
Alternatively, use the withCString()
method of String
:
func removeFile(_ path: String) {
let result = path.withCString {
libssh2_sftp_unlink_ex(sftpHandle, $0, UInt32(strlen($0)))
}
}
Even simpler: use the variant with needs only a C string and not an explicit string length. Here the compiler automatically creates the code to convert the Swift string to a temporary C string:
func removeFile(_ path: String) {
let result = libssh2_sftp_unlink(sftpHandle, path)
}
(Does not work because libssh2_sftp_unlink
is a macro and not imported to Swift.)