What is the canonical way to create network packets in Objective C? - objective-c

Coming from python I could do something like this.
values = (1, 'ab', 2.7)
s = struct.Struct('I 2s f')
packet = s.pack(*values)
I can pack together arbitrary types together very simply with python. What is the standard way to do it in Objective C?

Using a C struct is the normal approach. For example:
typedef struct {
int a;
char foo[2];
float b;
} MyPacket;
Would define a type for an int, 2 characters and a float. You can then interpret those bytes as a byte array for writing:
MyPacket p = {.a = 2, .b = 2.7};
p.foo[0] = 'a';
p.foo[1] = 'b';
char *toWrite = (char *)&p; // a buffer of size sizeof(p)

Not very clear a question, but maybe you're looking for a (packed struct)?
__attribute__((packed)) struct NetworkPacket {
int integer;
char character;
};

Related

How can I transfer data from unsigned char * to char * safely?

I am willing to transfer data from unsigned char hash[512 + 1] to char res[512 + 1] safely.
My C hashing library MHASH returns a result so it can be printed as listed below.
for (int i = 0; i < size /*hash block size*/; i++)
printf("%.2x", hash[i]); // which is unsigned char - it prints normal hash characters in range [a-z,0-9]
printf("\n");
I am willing to do something like that (see below).
const char* res = (const char *)hash; // "hash" to "res"
printf("%s\n", res); // print "res" (which is const char*) - if i do this, unknown characters are printed
I know the difference between char and unsigned char, but I don't know how to transfer data. Any answer would be greatly appreciated, thanks in advance. But please do not recommend me C++ (STD) code, I am working on a project that is not STD-linked.
Given that the contents of the unsigned char array are printable characters, you can always safely convert it to char. Either a hardcopy with memcpy or a pointer reference as in the code you have already written.
I'm guessing that the actual problem here is that the unsigned char array contents are not actually printable characters, but integers in some format. You'll have to convert them from integer to ASCII letters. How to do this depends on the format of the data, which isn't clear in your question.
Assuming the following:
#define ARR_SIZE (512 + 1)
unsigned char hash[ARR_SIZE];
char res[ARR_SIZE];
/* filling up hash here. */
Just do:
#include <string.h>
...
memcpy(res, hash, ARR_SIZE);
Well, thank you guys for your answers, but unfortunately nothing worked yet. I am now sticking with the code below.
char res[(sizeof(hash) * 2) + 1] = { '\0' };
char * pPtr = res;
for (int i = 0; i < hashBlockSize; i++)
sprintf(pPtr + (i * 2), "%.2x", hash[i]);
return (const char *)pPtr;
Until there is any other much more performant way to get this done. It's right, my question is strongly related to MHASH Library.

How to pass variable length structure to pinvoke C function in C#

My C structure format is this:
typedef struct pt_data {
int Length; ///< Length of the Data field in bytes
uchar Data[1]; ///< The data itself, variable length
} PT_DATA;
My C function is this:
PT_STATUS PTSetFingerData (
IN PT_CONNECTION hConnection,
IN PT_LONG lSlotNr,
IN PT_DATA *pFingerData
)
Now I want to put a wrapper for this function in C#.
How can I do this? In particular, how can I do this for passing the C# PT_DATA struct to PT_DATA C struct?
You need to marshal the data manually. A variable length struct cannot be marshalled by the p/invoke marshaller.
In your case the obvious way to do this would be to declare the PTDATA* argument as byte[] in your p/invoke. Then you just need to populated the byte array before calling the function. The first 4 bytes are the length of the subsequent data.
static byte[] GetPTData(byte[] arr)
{
byte[] len = BitConverter.GetBytes(arr.Length);
byte[] data = new byte[sizeof(int) + arr.Length];
Array.Copy(len, data, sizeof(int));
Array.Copy(arr, 0, data, sizeof(int), arr.Length);
return data;
}

How to do memcmp() in Swift?

I'm trying to convert some of my code from Objective-C to Swift. One method that I'm having trouble with does a comparison of a CBUUID with an UInt16. This was fairly straight-forward in Objective-C, but I'm having a hard time coming up with a good way to do this in Swift.
Here's the Objective-C version:
/*
* #method compareCBUUIDToInt
*
* #param UUID1 UUID 1 to compare
* #param UUID2 UInt16 UUID 2 to compare
*
* #returns 1 (equal) 0 (not equal)
*
* #discussion compareCBUUIDToInt compares a CBUUID to a UInt16 representation of a UUID and returns 1
* if they are equal and 0 if they are not
*
*/
-(int) compareCBUUIDToInt:(CBUUID *)UUID1 UUID2:(UInt16)UUID2 {
char b1[16];
[UUID1.data getBytes:b1];
UInt16 b2 = [self swap:UUID2];
if (memcmp(b1, (char *)&b2, 2) == 0) return 1;
else return 0;
}
My (untested) version of this method in Swift got much more complicated and I'm hoping that I'm just missing some better ways to use the language:
func compareCBUUID(CBUUID1: CBUUID, toInt CBUUID2: UInt16) -> Int {
let uuid1data = CBUUID1.data
let uuid1count = uuid1data.length / sizeof(UInt8)
var uuid1array = [UInt8](count: uuid1count, repeatedValue: 0)
uuid1data.getBytes(&uuid1array, length: uuid1count * sizeof(UInt8))
// #todo there's gotta be a better way to do this
let b2: UInt16 = self.swap(CBUUID2)
var b2Array = [b2 & 0xff, (b2 >> 8) & 0xff]
if memcmp(&uuid1array, &b2Array, 2) == 0 {
return 1
}
return 0
}
There are two things that seem to complicate things. First, it isn't possible to declare a fixed sized buffer in Swift, so the char b1[16] in ObjC becomes 3 lines in Swift. Second, I don't know of a way to do a memcmp() in Swift with a UInt16. The compiler complains that:
'UInt16' is not convertible to '#value inout $T5'
So that's where the clunky step comes in where I separate out the UInt16 into a byte array by hand.
Any suggestions?
The corresponding Swift code for char b1[16] would be
var b1 = [UInt8](count: 16, repeatedValue: 0)
and for the byte swapping you can use the "built-in" method byteSwapped
or bigEndian.
Casting the pointer for memcpy() is a bit tricky.
The direct translation of your Objective-C code to Swift would be (untested!):
var b1 = [UInt8](count: 16, repeatedValue: 0)
CBUUID1.data.getBytes(&b1, length: sizeofValue(b1))
var b2: UInt16 = CBUUID2.byteSwapped
// Perhaps better:
// var b2: UInt16 = CBUUID2.bigEndian
if memcmp(UnsafePointer(b1), UnsafePointer([b2]), 2) == 0 {
// ...
}
However, if you define b1 as an UInt16 array then you don't need
memcmp() at all:
var b1 = [UInt16](count: 8, repeatedValue: 0)
CBUUID1.data.getBytes(&b1, length: sizeofValue(b1))
var b2: UInt16 = CBUUID2.bigEndian
if b1[0] == b2 {
// ...
}

c and objective-c -- const char* and char*

I have a function:
-(void)ADPCMDecode:(char *)indata : (short *)outdata :(long)len {
indata is a char and the function does pointer arithmetic to iterate for a length of len, modifying outdata, which is a short and I will need to do pointer arithmetic to get the values from it.
I am attempting to call the function using:
const char *modulatedBytes1 = [modulatedAudio bytes];
char *modulatedBytes [] = modulatedBytes1;
unsigned int moduleatedLength = [modulatedAudio length];
short *decompressedBytes = NULL;
[self ADPCMDecode:modulatedBytes :decompressedBytes :moduleatedLength];
DLog(#"%hi",decompressedBytes[1]);
I get a BAD ACCESS error on this line: *outp++ = valprev; within the function, because I am passing a constant char * instead of a char *
How should I call the function, and how would I get the output from it?
I have no background in C, which is why I do not understand how to go about doing this.
Here is the C only version of the same question:
https://pastee.org/d3y3z

byte array to double

I have a four byte char array and I want to convert it to double. How can I achieve this in C.
float and double are so closely related in C that an explicit conversion is probably not needed. However, it would be necessary for transmission to another system, or to match a data format specification. This will do what you ask:
union {
char c [4];
float f;
} x;
double d;
memcpy (x.c, character_source, sizeof x.c);
d = x.f;