Convert a Swift Array of String to a to a C string array pointer - swift

I'm on Swift 3, and I need to interact with an C API, which accepts a NULL-terminated list of strings, for example
const char *cmd[] = {"name1", "value1", NULL};
command(cmd);
In Swift, the API was imported like
func command(_ args: UnsafeMutablePointer<UnsafePointer<Int8>?>!)
After trying hundreds of times using type casting or unsafeAddress(of:) I still cannot get this work. Even though I pass a valid pointer that passed compilation, it crashes at runtime saying invalid memory access (at strlen function). Or maybe it's something about ARC?
let array = ["name1", "value1", nil]
// ???
// args: UnsafeMutablePointer<UnsafePointer<Int8>?>
command(args)

You can proceed similarly as in How to pass an array of Swift strings to a C function taking a char ** parameter. It is a bit different because of the different
const-ness of the argument array, and because there is a terminating
nil (which must not be passed to strdup()).
This is how it should work:
let array: [String?] = ["name1", "name2", nil]
// Create [UnsafePointer<Int8>]:
var cargs = array.map { $0.flatMap { UnsafePointer<Int8>(strdup($0)) } }
// Call C function:
let result = command(&cargs)
// Free the duplicated strings:
for ptr in cargs { free(UnsafeMutablePointer(mutating: ptr)) }

This class provides a pointer that works with char** and automatically deallocates the memory, even though it's a struct (using a little trick with a mapped data with deallocator).
public struct CStringArray {
public let pointer: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>
public let count: Int
private var data: Data
public init(_ array: [String]) {
let count = array.count
// Allocate memory to hold the CStrings and a terminating nil
let pointer = UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>.allocate(capacity: count + 1)
pointer.initialize(repeating: nil, count: count + 1) // Implicit terminating nil at the end of the array
// Populate the allocated memory with pointers to CStrings
var e = 0
array.forEach {
pointer[e] = strdup($0)
e += 1
}
// This uses the deallocator available on the data structure as a solution to the fact that structs do not have `deinit`
self.data = Data(bytesNoCopy: pointer, count: MemoryLayout<UnsafeMutablePointer<CChar>>.size * count, deallocator: .custom({_,_ in
for i in 0...count - 1 {
free(pointer[i])
}
pointer.deallocate()
}))
self.pointer = pointer
self.count = array.count
}
public subscript(index: Data.Index) -> UnsafeMutablePointer<CChar>? {
get {
precondition(index >= 0 && index < count, "Index out of range")
return pointer[index]
}
}
public subscript(index: Data.Index) -> String? {
get {
precondition(index >= 0 && index < count, "Index out of range")
if let pointee = pointer[index] {
return String(cString: pointee)
}
return nil
}
}
}

Related

Assigning values to tuple in for loop

There is a tuple of UInt8's in a struct MIDIPacket.
Normal assignment is like this:
import CoreMIDI
let packet = MIDIPacket()
packet.data.0 = 0x02
packet.data.1 = 0x5f
and so on.
This tuple has length of ~128+. There is an array of values, converted, which I would like to assign to the packet beginning at a certain index.
let converted = [0x01, 0x02, 0x5e,...]
var k = packet starting index of assignment
for i in 0..<converted.count {
packet.data(k) = converted[i]
k += 1
}
How do I do this?
subscripting doesn't work: e.g. packet.data[i], while I believe Mirror simply creates a copy of the packet, so assigning to it would not work..
let bytes = Mirror(reflecting: packet.data).children;
for (_, b) in bytes.enumerated() {
}
There's no official API for doing this, but IIRC, tuples of homogeneous element types are guaranteed to have a contiguous memory layout. You take advantage of this by using UnsafeBufferPointer to read/write to the tuple.
Usually this requires you to manually hard-code the tuple's element count, but I wrote some helper functions that can do this for you. There's two variants, a mutable one, which lets you obtain an UnsafeBufferPointer, which you can read (e.g. to create an Array), and a mutable one, which gives you a UnsafeMutableBufferPointer, through which you can assign elements.
enum Tuple {
static func withUnsafeBufferPointer<Tuple, TupleElement, Result>(
to value: Tuple,
element: TupleElement.Type,
_ body: (UnsafeBufferPointer<TupleElement>) throws -> Result
) rethrows -> Result {
try withUnsafePointer(to: value) { tuplePtr in
let count = MemoryLayout<Tuple>.size / MemoryLayout<TupleElement>.size
return try tuplePtr.withMemoryRebound(
to: TupleElement.self,
capacity: count
) { elementPtr in
try body(UnsafeBufferPointer(start: elementPtr, count: count))
}
}
}
static func withUnsafeMutableBufferPointer<Tuple, TupleElement, Result>(
to value: inout Tuple,
element: TupleElement.Type,
_ body: (UnsafeMutableBufferPointer<TupleElement>) throws -> Result
) rethrows -> Result {
try withUnsafeMutablePointer(to: &value) { tuplePtr in
let count = MemoryLayout<Tuple>.size / MemoryLayout<TupleElement>.size
return try tuplePtr.withMemoryRebound(
to: TupleElement.self,
capacity: count
) { elementPtr in
try body(UnsafeMutableBufferPointer(start: elementPtr, count: count))
}
}
}
}
var destinationTouple: (Int, Int, Int, Int) = (0, 0, 0, 0) // => (0, 0, 0, 0)
var sourceArray = Array(1...4)
print("before:", destinationTouple)
Tuple.withUnsafeMutableBufferPointer(to: &destinationTouple, element: Int.self) { (destBuffer: UnsafeMutableBufferPointer<Int>) -> Void in
sourceArray.withUnsafeMutableBufferPointer { sourceBuffer in
// buffer[...] = 1...
destBuffer[destBuffer.indices] = sourceBuffer[destBuffer.indices]
return ()
}
}
print("after:", destinationTouple) // => (1, 2, 3, 4)

Is there a way to retrieve directly the value returned from a closure in Swift, with type the return type of the closure and not: () -> Type

This is a question that aims merely at elegance, but is there a way to make something to the following code work in Swift? I know the code does not work, what I want is that the result of the code within the closure is stored in a constant. And the underlying theoretical issue is whether or not it is possible to retrieve the returned value from the closure with type Int and not with type () -> Int.
Thanks a lot for any help or comment!
let tableWithBooleans: [Bool] = Array(repeating: false, count: 10)
tableWithBooleans[0] = true
tableWithBooleans[5] = true
let numberOfTrue: Int = {
var result: Int = 0
for i in 0...9 {
if tableWithBooleans[i] {
result += 1
}
}
return result
}
// I want the code to compile and numberOfTrue to be a constant equal to 2
Use a high-order function instead
let numberOfTrue = tableWithBooleans.reduce(0) { $1 ? $0 + 1 : $0 }
Now if you still want to use your closure code then you should add a () after the closing } since you are calling the code inside {} as a function
let numberOfTrue: Int = {
var result: Int = 0
for i in 0...9 {
if tableWithBooleans[i] {
result += 1
}
}
return result
}()

Copying swift string to fixed size char[][]

I have a C struct like this.
struct someStruct {
char path[10][MAXPATHLEN];
};
I'd like to copy a list of Swift strings into the char[10][] array.
For me it's very challenging to handle c two-dimensional char array in Swift. Could anyone share some code which can work with Swift 5? Thanks!
C Arrays are imported to Swift as tuples. Here we have a two-dimensional C array, which becomes a nested tuple in Swift:
public struct someStruct {
public var path: (
(Int8, ..., Int8),
(Int8, ..., Int8),
...
(Int8, ..., Int8)
)
}
There is no really “nice” solution that I am aware of, but using the fact that Swift preserves the memory layout of imported C structures (source), one can achive the goal with some pointer magic:
var s = someStruct()
let totalSize = MemoryLayout.size(ofValue: s.path)
let itemSize = MemoryLayout.size(ofValue: s.path.0)
let numItems = totalSize / itemSize
withUnsafeMutablePointer(to: &s.path) {
$0.withMemoryRebound(to: Int8.self, capacity: totalSize) { ptr in
for i in 0..<numItems {
let itemPtr = ptr + i * itemSize
strlcpy(itemPtr, "String \(i)", itemSize)
}
print(ptr)
}
}
ptr is a pointer to s.path, and itemPtr is pointer to s.path[i]. strlcpy copies the string, here we use the fact that one can pass a Swift string directly to a C function taking a const char* argument (and a temporary null-terminated UTF-8 representation is created automatically).
I strongly encourage you to use some kind of helper methods.
Example:
/* writes str to someStruct instance at index */
void writePathToStruct(struct someStruct* s, size_t index, const char* str) {
assert(index < 10 && "Specified index is out of bounds");
strcpy(s->path[index], str);
}
Now, when calling this function, filling the array looks much cleaner:
var someStructInstance = someStruct()
let pathIndex: Int = 3
let path = "/dev/sda1"
let encoding = String.Encoding.ascii
withUnsafeMutablePointer(to: &someStructInstance) { pointer -> Void in
writePathToStruct(pointer, pathIndex, path.cString(using: encoding)!)
}
By design, tuples can not be accessed by variable index. Reading statically can thus be done without a helper function.
let pathRead = withUnsafeBytes(of: &someStructInstance.path.3) { pointer -> String? in
return String(cString: pointer.baseAddress!.assumingMemoryBound(to: CChar.self), encoding: encoding)
}
print(pathRead ?? "<Empty path>")
However, I assume you will definitely have to read the array with a dynamic index.
In that case, I encourage you to use a helper method as well:
const char* readPathFromStruct(const struct someStruct* s, size_t index) {
assert(index < 10 && "Specified index is out of bounds");
return s->path[index];
}
which will result in a much cleaner Swift code:
pathRead = withUnsafePointer(to: &someStructInstance) { pointer -> String? in
return String(cString: readPathFromStruct(pointer, 3), encoding: encoding)
}

How to change the value of a child from a Mirror introspection

I'm doing a bunch of BLE in iOS, which means lots of tight packed C structures being encoded/decoded as byte packets. The following playground snippets illustrate what I'm trying to do generically.
import Foundation
// THE PROBLEM
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var c:UInt8 = 0
}
sizeof(Thing) // --> 9 :(
var thing = Thing(a: 0x42, b: 0xDEADBEAF, c: 0x13)
var data = NSData(bytes: &thing, length: sizeof(Thing)) // --> <42000000 afbeadde 13> :(
So given a series of fields of varying size, we don't get the "tightest" packing of bytes. Pretty well known and accepted. Given my simple structs, I'd like to be able to arbitrarily encode the fields back to back with no padding or alignment stuff. Relatively easy actually:
// ARBITRARY PACKING
var mirror = Mirror(reflecting: thing)
var output:[UInt8] = []
mirror.children.forEach { (label, child) in
switch child {
case let value as UInt32:
(0...3).forEach { output.append(UInt8((value >> ($0 * 8)) & 0xFF)) }
case let value as UInt8:
output.append(value)
default:
print("Don't know how to serialize \(child.dynamicType) (field \(label))")
}
}
output.count // --> 6 :)
data = NSData(bytes: &output, length: output.count) // --> <42afbead de13> :)
Huzzah! Works as expected. Could probably add a Class around it, or maybe a Protocol extension and have a nice utility. The problem I'm up against is the reverse process:
// ARBITRARY DEPACKING
var input = output.generate()
var thing2 = Thing()
"\(thing2.a), \(thing2.b), \(thing2.c)" // --> "0, 0, 0"
mirror = Mirror(reflecting:thing2)
mirror.children.forEach { (label, child) in
switch child {
case let oldValue as UInt8:
let newValue = input.next()!
print("new value for \(label!) would be \(newValue)")
// *(&child) = newValue // HOW TO DO THIS IN SWIFT??
case let oldValue as UInt32: // do little endian
var newValue:UInt32 = 0
(0...3).forEach {
newValue |= UInt32(input.next()!) << UInt32($0 * 8)
}
print("new value for \(label!) would be \(newValue)")
// *(&child) = newValue // HOW TO DO THIS IN SWIFT??
default:
print("skipping field \(label) of type \(child.dynamicType)")
}
}
Given an unpopulated struct value, I can decode the byte stream appropriately, figure out what the new value would be for each field. What I don't know how to do is to actually update the target struct with the new value. In my example above, I show how I might do it with C, get the pointer to the original child, and then update its value with the new value. I could do it easily in Python/Smalltalk/Ruby. But I don't know how one can do that in Swift.
UPDATE
As suggested in comments, I could do something like the following:
// SPECIFIC DEPACKING
extension GeneratorType where Element == UInt8 {
mutating func _UInt8() -> UInt8 {
return self.next()!
}
mutating func _UInt32() -> UInt32 {
var result:UInt32 = 0
(0...3).forEach {
result |= UInt32(self.next()!) << UInt32($0 * 8)
}
return result
}
}
extension Thing {
init(inout input:IndexingGenerator<[UInt8]>) {
self.init(a: input._UInt8(), b: input._UInt32(), c: input._UInt8())
}
}
input = output.generate()
let thing3 = Thing(input: &input)
"\(thing3.a), \(thing3.b), \(thing3.c)" // --> "66, 3735928495, 19"
Basically, I move the various stream decoding methods to byte stream (i.e. GeneratorType where Element == UInt8), and then I just have to write an initializer that strings those off in the same order and type the struct is defined as. I guess that part, which is essentially "copying" the structure definition itself (and therefore error prone), is what I had hoped to use some sort of introspection to handle. Mirrors are the only real Swift introspection I'm aware of, and it seems pretty limited.
As discussed in the comments, I suspect this is over-clever. Swift includes a lot of types not friendly to this approach. I would focus instead on how to make the boilerplate as easy as possible, without worrying about eliminating it. For example, this is very sloppy, but is in the direction I would probably go:
Start with some helper packer/unpacker functions:
func pack(values: Any...) -> [UInt8]{
var output:[UInt8] = []
for value in values {
switch value {
case let i as UInt32:
(0...3).forEach { output.append(UInt8((i >> ($0 * 8)) & 0xFF)) }
case let i as UInt8:
output.append(i)
default:
assertionFailure("Don't know how to serialize \(value.dynamicType)")
}
}
return output
}
func unpack<T>(bytes: AnyGenerator<UInt8>, inout target: T) throws {
switch target {
case is UInt32:
var newValue: UInt32 = 0
(0...3).forEach {
newValue |= UInt32(bytes.next()!) << UInt32($0 * 8)
}
target = newValue as! T
case is UInt8:
target = bytes.next()! as! T
default:
// Should throw an error here probably
assertionFailure("Don't know how to deserialize \(target.dynamicType)")
}
}
Then just call them:
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var c:UInt8 = 0
func encode() -> [UInt8] {
return pack(a, b, c)
}
static func decode(bytes: [UInt8]) throws -> Thing {
var thing = Thing()
let g = anyGenerator(bytes.generate())
try unpack(g, target: &thing.a)
try unpack(g, target: &thing.b)
try unpack(g, target: &thing.c)
return thing
}
}
A little more thought might be able to make the decode method a little less repetitive, but this is still probably the way I would go, explicitly listing the fields you want to encode rather than trying to introspect them. As you note, Swift introspection is very limited, and it may be that way for a long time. It's mostly used for debugging and logging, not logic.
I have tagged Rob's answer is the official answer. But I'd thought I'd share what I ended up doing as well, inspired by the comments and answers.
First, I fleshed out my "Problem" a little to include a nested structure:
struct Inner {
var ai:UInt16 = 0
var bi:UInt8 = 0
}
struct Thing {
var a:UInt8 = 0
var b:UInt32 = 0
var inner = Inner()
var c:UInt8 = 0
}
sizeof(Thing) // --> 12 :(
var thing = Thing(a: 0x42, b: 0xDEADBEAF, inner: Inner(ai: 0x1122, bi: 0xDD), c: 0x13)
var data = NSData(bytes: &thing, length: sizeof(Thing)) // --> <42000000 afbeadde 2211dd13> :(
For Arbitrary Packing, I stuck with the same generic approach:
protocol Packable {
func packed() -> [UInt8]
}
extension UInt8:Packable {
func packed() -> [UInt8] {
return [self]
}
}
extension UInt16:Packable {
func packed() -> [UInt8] {
return [(UInt8((self >> 0) & 0xFF)), (UInt8((self >> 8) & 0xFF))]
}
}
extension UInt32:Packable {
func packed() -> [UInt8] {
return [(UInt8((self >> 0) & 0xFF)), (UInt8((self >> 8) & 0xFF)), (UInt8((self >> 16) & 0xFF)), (UInt8((self >> 24) & 0xFF))]
}
}
extension Packable {
func packed() -> [UInt8] {
let mirror = Mirror(reflecting:self)
var bytes:[UInt8] = []
mirror.children.forEach { (label, child) in
switch child {
case let value as Packable:
bytes += value.packed()
default:
print("Don't know how to serialize \(child.dynamicType) (field \(label))")
}
}
return bytes
}
}
Being able to "pack" things is as easy adding them to the Packable protocol and telling them to pack themselves. For my cases above, I only need 3 different types of signed integers, but one could add lots more. For example, in my own code, I have some Enums derived from UInt8 which I added the packed method to.
extension Thing:Packable { }
extension Inner:Packable { }
var output = thing.packed()
output.count // --> 9 :)
data = NSData(bytes: &output, length: output.count) // --> <42afbead de2211dd 13> :)
To be able to unpack stuff, I came up with a little bit of support:
protocol UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> Self
}
extension UInt8:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt8 {
return input.next()!
}
}
extension UInt16:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt16 {
return UInt16(input.next()!) | (UInt16(input.next()!) << 8)
}
}
extension UInt32:UnpackablePrimitive {
static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt32 {
return UInt32(input.next()!) | (UInt32(input.next()!) << 8) | (UInt32(input.next()!) << 16) | (UInt32(input.next()!) << 24)
}
}
With this, I can then add initializers to my high level structures, e.g.
extension Inner:Unpackable {
init(inout packed bytes:IndexingGenerator<[UInt8]>) {
self.init(ai: UInt16.unpack(&bytes), bi: UInt8.unpack(&bytes))
}
}
extension Thing:Unpackable {
init(inout packed bytes:IndexingGenerator<[UInt8]>) {
self.init(a: UInt8.unpack(&bytes), b: UInt32.unpack(&bytes), inner: Inner(packed:&bytes), c: UInt8.unpack(&bytes))
}
}
What I liked about this is that these initializers call the default initializer in the same order and types as the structure is defined. So if the structure changes in type or order, I have to revisit the (packed:) initializer. The kids a bit long, but not too.
What I didn't like about this, was having to pass the inout everywhere. I'm honestly not sure what the value is of value based generators, since passing them around you almost always want to share state. Kind of the whole point of reifying an object that captures the position of a stream of data, is to be able to share it. I also don't like having to specify IndexingGenerator directly, but I imagine there's some fu magic that would make that less specific and still work, but I'm not there yet.
I did play with something more pythonic, where I return a tuple of the type and the remainder of a passed array (rather than a stream/generator), but that wasn't nearly as easy to use at the top level init level.
I also tried putting the static methods as extensions on byte based generators, but you have to use a function (would rather have used a computed var with side effects) there whose name doesn't match a type, so you end up with something like
self.init(a: bytes._UInt8(), b: bytes._UInt32(), inner: Inner(packed:&bytes), c: bytes._UInt8())
This is shorter, but doesn't put the type like functions next to the argument names. And would require all kinds of application specific method names to be added as well as one extended the set of UnpackablePrimitives.

Nested Swift Dictionaries

I want to initialize a dictionary with a dictionary nested inside like this:
var a = [Int:[Int:Float]]()
a[1][2] = 12
But I get an error:
(Int:[Int:Float]) does not have a member named 'subscript'
I've hacked at a variety of other approaches, all of them running into some kind of issue.
Any idea why this doesn't work?
You can create your own 2D dictionary like this:
struct Dict2D<X:Hashable,Y:Hashable,V> {
var values = [X:[Y:V]]()
subscript (x:X, y:Y)->V? {
get { return values[x]?[y] }
set {
if values[x] == nil {
values[x] = [Y:V]()
}
values[x]![y] = newValue
}
}
}
var a = Dict2D<Int,Int,Float>()
a[1,2] = 12
println(a[1,2]) // Optional(12.0)
println(a[0,2]) // nil
The point is you access the element via a[x,y] instead of a[x][y] or a[x]?[y].
It's giving you that error because your first subscript returns an optional so it may return a dictionary or nil. In the case that it returns nil the second subscript would be invalid. You can force it to unwrap the optional value by using an exlamation point.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]![2]
If you aren't positive that a[1] is non-nil you may want to safely unwrap with a question mark instead.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]?[2]
You can also assign using this method. (As of Beta 5)
var a = [Int:[Int:Float]]()
a[1] = [Int: Float]()
a[1]?[2] = 12.0
a[1]?[2] //12.0
Another way to do it is with an extension to the standard dictionary:
extension Dictionary {
mutating func updateValueForKey(key: Key, updater: ((previousValue: Value?) -> Value)) {
let previousValue = self[key]
self[key] = updater(previousValue: previousValue)
}
}
Example:
var a = [Int:[Int:Float]]()
a.updateValueForKey(1) { nestedDict in
var nestedDict = nestedDict ?? [Int:Float]()
nestedDict[2] = 12
return nestedDict
}