How to convert Data into struct in Swift

I get a method call back and give me the Swift "Data" struct, I need to convert it into this struct below, how can it do? struct ins_gyro_info {   int64_t timestamp;   //millisecond   double gravity_x;   double gravity_y;   double gravity_z;   double rotation_x;   double rotation_y;   double rotation_z; };

#pragma

Answered by Scott J in 703531022

Assuming the Data object contains bytes laid out exactly the same as struct ins_gyro_info in C/C++, and that structure is imported into Swift, then you can use Swift’s “unsafe” memory API to perform the conversion.

If “unsafe” is a new area for you, I recommend starting by watching Safely Manage Pointers in Swift from WWDC20.

That said, here’s one way to accomplish what you want:

let data = readRawGyroInfoDataFromCameraOrWhatever()
let gyroInfo = data.withUnsafeBytes { buffer in
    buffer.load(as: ins_gyro_info.self)
}

You can better show your target struct in a code block, like this;

struct ins_gyro_info {   
	int64_t timestamp;   //millisecond   
	double gravity_x;   
	double gravity_y;   
	double gravity_z;   
	double rotation_x;   
	double rotation_y;   
	double rotation_z; 
};

Then the question is, what is the format of your Data? What method is returning it, and how is it structured?

Then we can convert from your Data to your struct.

If you get from JSON, in jsonData, you will have to use code like this:

 // name should start with UpperCase and be CamelCase: InsGyroInfo
struct InsGyroInfo: Codable {    
  // Your struct
}

let gyroInfo = try JSONDecoder().decode(InsGyroInfo.self, from: jsonData)

not json,just binary data,the data came from 360 camera with bluetooth or wifi link ,it will call this function when data is prepared ,and I wanna use this gyro info in my Swift program

Accepted Answer

Assuming the Data object contains bytes laid out exactly the same as struct ins_gyro_info in C/C++, and that structure is imported into Swift, then you can use Swift’s “unsafe” memory API to perform the conversion.

If “unsafe” is a new area for you, I recommend starting by watching Safely Manage Pointers in Swift from WWDC20.

That said, here’s one way to accomplish what you want:

let data = readRawGyroInfoDataFromCameraOrWhatever()
let gyroInfo = data.withUnsafeBytes { buffer in
    buffer.load(as: ins_gyro_info.self)
}

contains bytes laid out exactly the same

… and with the same endianness. If you’re getting this data from a file, or from a network protocol, you can’t guarantee that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I’ll just claim that “exactly the same” included endianness, even if I didn’t think of it at the time. 😉

The context isn’t clear; the OP mentioned “method call back” which could mean the camera vendor provided a library/framework for communicating with the camera and it (presumably/hopefully) returns a blob compatible with its declaration of struct ins_gyro_info for the current platform. If so, great.

(I guessed this was the scenario since struct ins_gyro_info is a C declaration, possibly copied from a library header file.)

But the OP also mentioned Bluetooth and Wi-Fi explicitly, so maybe the app actually needs to connect directly to the camera via a platform API and process the data by referring to a documented wire format, without any help from a library. If so, and if the endianness doesn’t match, then indeed my code example won’t work.

In this latter case, it may be cleanest to implement the needed “marshaling” code in C and then call it from Swift. Hey, that sounds like the seed of the hypothetical camera support library I mentioned earlier.

I’ll just claim that “exactly the same” included endianness

I’ll allow that claim (-:

In this latter case, it may be cleanest to implement the needed “marshaling” code in C and then call it from Swift.

Personally I’ve stopped doing this with structures and now I just parse serialised data structures (network messages, file formats) byte-by-byte. Swift is really good at this because many of the abstractions get optimised away. And it avoids mucking around with pointers, which is a common cause of security vulnerabilities.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How to convert Data into struct in Swift
 
 
Q