Swift Convert String to Unsafemutablepointer<Int8>

Swift convert string to UnsafeMutablePointer Int8

Previous answers on StackOverflow using CString don't seem to work anymore

Nevertheless, UnsafePointer<Int8> is a C string. If your context absolutely requires an UnsafeMutablePointer, just coerce, like this:

let s = NSBundle.mainBundle().bundlePath
let cs = (s as NSString).UTF8String
var buffer = UnsafeMutablePointer<Int8>(cs)
swe_set_ephe_path(buffer)

Of course I don't have your swe_set_ephe_path, but it works fine in my testing when it is stubbed like this:

func swe_set_ephe_path(path: UnsafeMutablePointer<Int8>) {
println(String.fromCString(path))
}

Swift 4 convert String to UnsafeMutablePointer Int8

Follow up and Summary:

1) solution in link Swift convert string to UnsafeMutablePointer<Int8> is not valid in Swift 4 anymore.

2) To get an UnsafeMutablePointer(Int8) from a String, the simplest way is:

let contentPointer = strdup(content)

3) However, you should always keep in mind that it's caller's responsibility to free memory. Above code will use new memory and it must be deallocated afterwards.:

let contentPointer = strdup(content)
SendPing(content: contentPointer)
....

free(contentPointer)

Otherwise, you will face memory leak issue.

Swift: Turning a String into UnsafeMutablePointer Int8

First you should write a wrapper function in your bridging header that accepts char pointers then cast/create the emxArray_char_T in c IE:

// casting the func as void because you didn't specify

void predictWrapper(const char *aChar, char *bChar) {
// do your casting and call original func predictX010(...)
}

Then in swift (This isn't going to be pretty)

var arg: String = "some arg"
var arg2: String = "another arg"

// use closure to prevent dangling pointer
arg.withCString{ body in // body is UnsafePointer<Int8>
arg2.withCString{ body2 in // we'll cast this to UnsafeMutablePointer
var arg2Mutable = UnsafeMutablePointer<Int8>(mutating: body2)
//call your wrapper
predictWrapper(body, arg2Mutable)

}
}

You may be able to use the original types and function, but i've always found it easier (less banging my head on the desk) to use the most standard c types you can in swift and casting to custom/complex types in c

How to convert String to UnsafeMutablePointer UInt8 ? Swift 3

This is where you run into some complexity from having to work with C.

The primary concern here is the life time of the pointers you pass into that function. My code below uses pointers into the buffer of the Swift Strings. This will be an issue if the areKeysConsistent captures those pointers for later use. It's possible that ARC deallocates the Swift String, making those stored pointers become dangling pointers.

func areKeysConsistent(
_ cert: UnsafeMutablePointer<UInt8>, _ certLength: Int,
_ key: UnsafeMutablePointer<UInt8>, _ keyLength: Int,
_ pass: UnsafeMutablePointer<UInt8>, _ passLength: Int
) {
print(cert, key, pass)
}

let certificate = "cert"
let privateKey = "key"
let password = "password"

var certificateCString = certificate.utf8CString
var privateKeyCString = privateKey.utf8CString
var passwordCString = password.utf8CString


certificateCString.withUnsafeMutableBytes { certUMRBP in
privateKeyCString.withUnsafeMutableBytes { pkUMRBP in
passwordCString.withUnsafeMutableBytes { passUMRBP in

areKeysConsistent(
certUMRBP.baseAddress!.bindMemory(to: UInt8.self, capacity: certUMRBP.count),
certUMRBP.count,
pkUMRBP.baseAddress!.bindMemory(to: UInt8.self, capacity: pkUMRBP.count),
pkUMRBP.count,
passUMRBP.baseAddress!.bindMemory(to: UInt8.self, capacity: passUMRBP.count),
passUMRBP.count
)
}
}
}

Is there a way to convert UnsafeMutablePointer String to UnsafeMutablePointer Int8 ?

A C string is an Unsafe[Mutable]Pointer<Int8>. There are ways to derive the C string from a Swift string, and there you are.

To demonstrate, I'll start with an Objective-C method that takes an UnsafeMutablePointer<Int8>. Here is the interface:

#import <Foundation/Foundation.h>

@interface Thing : NSObject

- (void) passMeACString: (nonnull char[]) s;

@end

Here is the implementation; it just prints the received C string, so we know we got one:

#import "Thing.h"

@implementation Thing

- (void) passMeACString: (nonnull char[]) s {
NSLog(@"%s", s);
}

@end

Now, if you look at the generated interface, you'll see this:

open class Thing : NSObject {
open func passMeACString(_ s: UnsafeMutablePointer<Int8>)
}

So, you see? It takes an UnsafeMutablePointer<Int8>. Now I'll make one in Swift:

    let s = "0,281411,-78,521074,-3,344657,132,347776,-93,25,44"
var arr = s.cString(using: .utf8)!
let t = Thing()
t.passMeACString(&arr)

Result: 0,281411,-78,521074,-3,344657,132,347776,-93,25,44 is printed in the log. It worked.

UnsafeMutablePointer Int8 from String in Swift

The "problem" is that the first two parameters are declared as char *
and not as const char *, even if the strings are not modified by the function:

int dgeev_(char *__jobvl, char *__jobvr, ...);

is mapped to Swift as

func dgeev_(__jobvl: UnsafeMutablePointer<Int8>, __jobvr: UnsafeMutablePointer<Int8>, ...) -> Int32;

A possible workaround is

let result = "N".withCString { 
dgeev_(UnsafeMutablePointer($0), UnsafeMutablePointer($0), &N, ...)
}

Inside the block, $0 is a pointer to a NUL-terminated array of char with the
UTF-8 representation of the string.


Remark: dgeev_() does not modify the strings pointed to by the first two arguments,
so it "should be" declared as

int dgeev_(const char *__jobvl, const char *__jobvr, ...);

which would be mapped to Swift as

func dgeev_(__jobvl: UnsafePointer<Int8>, __jobvr: UnsafePointer<Int8>, ...) -> Int32;

and in that case you could simply call it as

let result = dgeev_("N", "N", &N, ...)

because Swift strings are converted to UnsafePointer<Int8>) automatically,
as explained in String value to UnsafePointer<UInt8> function parameter behavior.

How to convert String to UnsafePointer UInt8 and length

You have to convert the string to UTF-8 data first

let string = "foo bar"
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!

and then write it to the output stream

let outputStream: NSOutputStream = ... // the stream that you want to write to
let bytesWritten = outputStream.write(UnsafePointer(data.bytes), maxLength: data.length)

The UnsafePointer() cast is necessary because data.bytes has the type UnsafePointer<Void>, and not UnsafePointer<UInt8> as expected by the write()
method.


Update for Swift 3:

let string = "foo bar"
// Conversion to UTF-8 data (cannot fail):
let data = string.data(using: String.Encoding.utf8)!

// Write to output stream:
let outputStream: NSOutputStream = ... // the stream that you want to write to
let bytesWritten = data.withUnsafeBytes { outputStream.write($0, maxLength: data.count) }


Related Topics



Leave a reply



Submit