0

First, I am coming from a C programming background. My system consists of a device that is using software written in C language which utilizes Bluetooth to talk to the iPhone Application. I have a struct defined on the C device that I send byte by byte through Bluetooth and I am trying to reconstruct the struct in Swift.

In C, I would use a pointer to the array of bytes and simply typecast it to a pointer of my custom struct type:

uint8_t arrayOfBytes[16];

CustomStructType_t * structPtr = (CustomStructType_t *)arrayOfBytes;

In C, this is simple. I had an array of bytes, but I used typecasting to represent it as a custom struct instead.

Now on the iPhone, I capture the incoming Bluetooth bytes using Core Bluetooth. When a characteristic is updated, the following line accepts the bluetooth packet and converts it from Data type to String of bytes.

let incomingByteString = String(data: receivedBluetoothDataPacket, encoding: String.Encoding.utf8)

I'm honestly super lost at this point. I want to use this packet to initialize, or update the values of a struct object, lets say:

struct CustomStruct {
  let name: String!
  let value: Int
}

It would be nice if I could just tell Swift, Hey, I want you to create a CustomStruct object out of this incomingByteString.

Looks like this is going to be a real pain, and I may need to format the incoming packet much differently to accommodate Swift. Any advice is appreciated.

Matt
  • 3
  • 1
  • 2
  • From this 16 bytes, what range are `name: String` and `value: Int`? For example do you now that first 10 bytes is name and the rest is value or it's dynamic? – vpoltave Jun 03 '20 at 06:49
  • This probably will help you: https://stackoverflow.com/questions/28916535/swift-structs-to-nsdata-and-back – vpoltave Jun 03 '20 at 06:51
  • @vpoltave You've already identified a key problem I need to resolve. The answer to your question is Yes, I do know precisely how many bytes are allocated for each member of the struct. However, the number of bytes allocated are defined on the C device. When it comes to swift I am not sure how to ensure that a struct member of type String is of size 10 bytes, for example. I need to be sure that in Swift, each member takes up a defined amount of bytes in memory, otherwise a simple byte pointer conversion would not work. – Matt Jun 06 '20 at 15:53

1 Answers1

1

Try this

let bytes: [UInt8] = //get your bytes here
let customStruct = bytes.withUnsafeBufferPointer {
    ($0.baseAddress!.withMemoryRebound(to: CustomStruct.self, capacity: 1) { $0 })
}.pointee

You would have to convert your receivedBluetoothDataPacket to [UInt8] and you haven't provided the exact type.

Assuming it's Data a simple [UInt8](receivedBluetoothDataPacket) should suffice.

Kamil.S
  • 5,205
  • 2
  • 22
  • 51
  • This is really helpful, but there appears to be a major problem if I wanted to include a String in the Struct. I know that the string would be a maximum of 16 bytes, but Swift does not appear to have a way of specifying strength length. So the block of memory that Swift creates for a struct does not seem to be contiguous and a simple byte copy using the starting address of the struct would fail. – Matt Jun 08 '20 at 15:55
  • I think your best shot would be 16 variables of `Int8` size and some struct method/computed property to finally yield it as a proper Swift `String`. – Kamil.S Jun 08 '20 at 16:05