24

As the title says, what is the correct way to convert UnsafeMutablePointer to String in swift?

//lets say x = UnsafeMutablePointer<Int8> 

var str = x.memory.????

I tried using x.memory.description obviously it is wrong, giving me a wrong string value.

2
  • What does the pointer point to? UTF-8 bytes? NUL-terminated? Commented Nov 28, 2015 at 18:19
  • Assuming it is a valid null-terminated C string, you can use String(CString:, encoding:). Commented Nov 28, 2015 at 18:21

4 Answers 4

58

If the pointer points to a NUL-terminated C string of UTF-8 bytes, you can do this:

import Foundation

let x: UnsafeMutablePointer<Int8> = ...
// or UnsafePointer<Int8>
// or UnsafePointer<UInt8>
// or UnsafeMutablePointer<UInt8>

let str = String(cString: x)
Sign up to request clarification or add additional context in comments.

1 Comment

let str = String.fromCString(x)
11

Times have changed. In Swift 3+ you would do it like this:

If you want the utf-8 to be validated:

let str: String? = String(validatingUTF8: c_str)

If you want utf-8 errors to be converted to the unicode error symbol: �

let str: String = String(cString: c_str)

Assuming c_str is of type UnsafePointer<UInt8> or UnsafePointer<CChar> which is the same type and what most C functions return.

Comments

2

this:

let str: String? = String(validatingUTF8: c_str)

doesn't appear to work with UnsafeMutablePointer<UInt8> (which is what appears to be in my data).

This is me trivially figuring out how to do something like the C/Perl system function:

let task = Process()
task.launchPath = "/bin/ls"
task.arguments = ["-lh"]

let pipe = Pipe()
task.standardOutput = pipe
task.launch()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
var unsafePointer = UnsafeMutablePointer<Int8>.allocate(capacity: data.count)
data.copyBytes(to: unsafePointer, count: data.count)

let output : String = String(cString: unsafePointer)
print(output)
//let output : String? = String(validatingUTF8: unsafePointer)
//print(output!)

if I switch to validatingUTF8 (with optional) instead of cString, I get this error:

./ls.swift:19:37: error: cannot convert value of type 'UnsafeMutablePointer<UInt8>' to expected argument type 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>')
let output : String? = String(validatingUTF8: unsafePointer)
                                    ^~~~~~~~~~~~~

Thoughts on how to validateUTF8 on the output of the pipe (so I don't get the unicode error symbol anywhere)?

(yes, I'm not doing proper checking of my optional for the print(), that's not the problem I'm currently solving ;-) ).

Comments

0

I've taken to using CustomStringConvertible conformance for this in my Swift 5 and Swift 6 projects.

// UnsafeMutablePointer<CChar> CustomStringConvertible conformance
extension UnsafeMutablePointer<CChar>: @retroactive CustomStringConvertible {
    public var description: String {
        return String(cString: self)
    }
}

Then from my SwiftUI views I'm able to do directly access UnsafeMutablePointer<CChar> and (optional) UnsafeMutablePointer<CChar>? values as follows:

// item.title is UnsafeMutablePointer<CChar>?
Text(item.title?.description ?? "Untitled")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.