1
votes

I'm trying to interact with a C API from Swift and was able to successfully convert unsigned char* to String but am not able to convert back a String to unsigned char *

Here is my C function that returns the passed string:

unsigned char* test(unsigned char* hello) {
    return hello;
}

Here is my swift code to call the c function which doesn't work:

let str = "hello, world!"
print(String(cString:test(str)))

Its goal is to pass "hello, world" to c and then have c pass "hello, world" back and then print it.

I've tried the solutions from here but they all seem outdated for Swift 4

Buffer attempt:

let buffer = UnsafeMutableBufferPointer.allocate(capacity: 4)

_ = buffer.initialize(from: 1...4)

print(String(cString: test(buffer)))

Error:

Cannot convert value of type 'UnsafeMutableBufferPointer' to expected argument type 'UnsafeMutablePointer!'

1
"I''ve tried the solutions from here" like what?Alexander
Returning the pointer that you get from an automatic String-to-pointer conversion is unsafe because its storage is only guaranteed to be valid for the duration of the call. If your C API actually does something like that, you won't be able to use automatic conversions.zneak
What is String?Weather Vane
@WeatherVane, it is the standard string type in Swift.zneak
You need to use UnsafeMutableBufferPointer.allocate, copy your string in there, do whatever you need to do, and then deallocate the buffer pointer.zneak

1 Answers

1
votes
  • You need to specify the Element type for UnsafeMutableBufferPointer.

  • The pointer to the content of UnsafeMutableBufferPointer can be accessed through the property baseAddress.

Try this:

let str = "hello, world!"

let buffer = UnsafeMutableBufferPointer<CUnsignedChar>.allocate(capacity: str.utf8.count + 1)
defer {buffer.deallocate()}

memcpy(buffer.baseAddress, str, str.utf8.count + 1)

print(String(cString: test(buffer.baseAddress)))