Excess elements in scalar initializer in byte create in iOS - ios

In my project, I create a byte:
Byte bytes = {0x7E, 0x7F};
But there comes a warning:
Excess elements in scalar initializer
What this mean? does it effect me?

You are trying to create single dimensional array where you are not declaring size of it there's no memory set aside for an array so that's why the compiler is generating a warning which may cause an runtime error ahead.
Set array size:
// single dimen
Byte bytes[2] = {0x7E, 0x7F};
// double dimen
Byte bytes[1][2] = {{0x7E, 0x7F}, {0x7E, 0x7F}};

how stupid! I create a byte array should be like this:
Byte bytes[] = {0x7E, 0x7F}
I did not write the [].

Related

Fatal error when using withMemoryRebound in iOS/Swift

I have the following code to create a table for sampling an image in iOS using the Swift accelerate functions
When I rebound the memory to UInt16 which the table creation expects from Int which is the original type I get a fatal error.
var arr = Array<Float>(repeating: 0, count: 163840)
arr.withUnsafeBufferPointer{
arr_pointer in do {
arr_pointer.withMemoryRebound(to: UInt16.self){ // This causes a FATAL ERROR
arr_r_pointer in do {
let table = vImageMultidimensionalTable_Create( arr_r_pointer.baseAddress!,
3, 3, dims_r_pointer.baseAddress!, kvImageMDTableHint_Float,
vImage_Flags(kvImageNoFlags), nil )
vImageMultiDimensionalInterpolatedLookupTable_PlanarF( &srcBuffer,
&destBuffer,nil,table!,
kvImageFullInterpolation,
vImage_Flags(kvImageNoFlags))
}
}
}
}
Could anyone point out my mistake here?
You should've read Note for withMemoryRebound function:
Note
Only use this method to rebind the buffer’s memory to a type with the same size and stride as the currently bound Element type. To
bind a region of memory to a type that is a different size, convert
the buffer to a raw buffer and use the bindMemory(to:) method.
Size of Float is 32 bits, size of UInt16 is 16 bits, so they don't have same size and cannot be rebound.
So you should do something like this:
arr.withUnsafeBufferPointer { pointer in
let raw = UnsafeRawBufferPointer(pointer)
let uints = raw.bindMemory(to: UInt16.self)
// use buffer pointer to `UInt16`s here
}
But also note, that each Float from initial array will be split in two UInt16 that way. I don't know if that's what you need.
Your original array arr is an array of Floats
var arr = Array<Float>(repeating: 0, count: 163840)
but you're trying to bind the pointer to a UInt16
arr_pointer.withMemoryRebound(to: UInt16.self)

How to Convert Float to NSData Bytes

Using the following code, I am attempting to convert three float values into a single NSData object, which I can then transmit over a serial port.
float kP = [[self.kPTextField stringValue] floatValue];
float kI = [[self.kITextField stringValue] floatValue];
float kD = [[self.kDTextField stringValue] floatValue];
float combined[] = {kP, kI, kD};
NSData *dataPackage = [NSData dataWithBytes:&combined length:sizeof(combined)];
[self.serialPort sendData:dataPackage];
The problem is that it doesn't seem to work very well. Whenever I use the "sizeof()" C function, it tells me that the "dataPackage" is only 8 bytes, even though 3 float values should total 12 bytes. I am receiving the data with an Arduino. It sees the bytes coming in, but they aren't legible at all. I don't think it's a problem on the Arduino side of things (but who knows?).
Any help would be appreciated! I'm not a CS major, just a bio major, and I've never learned this stuff in a formal way so I am sorry if my question is ridiculous. I've spent several hours searching the net about this problem and haven't found anything that helped.
EDIT: It turns out this code was completely correct. I made a simple mistake on the arduino side of things by using a struct instead of a union to take the bytes and convert them back into floats.
For others who may be in a similar predicament, a successful way to convert floats from bytes coming out of the serial port is the following:
(at top of implementation file)
union {
float pidVals[3];
byte bytes[12];
} pidUnion;
(inside loop)
if (Serial.available() > 11) {
for (int i = 0; i < 12; i++) {
pidUnion.bytes[i] = Serial.read();
}
}
//Now, you can get access to all three floats of data using pidUnion.pidVals[0], pidUnion.pidVals[1], etc.
This probably isn't the best or most reliable way to transmit data. There is no error-correcting mechanism or packet structure. But it does work in a pinch. I imagine you would probably want to find a way to create a packet of data along with a hash byte to make sure all of the data is correct on the other side, this code doesn't have any of that though.
There are multiple problems with your code.
First, you don't want to use stringValue on a text field. You want the text property, which is a string.
So the first line should read like this:
float kP = [self.kPTextField.text floatValue];
Second, in C, an array of things is a pointer. The data type of
float combined[]
and
float *combined
is identical. Both are "pointer to float".
So this code:
NSData *dataPackage = [NSData dataWithBytes:&combined
length: sizeof(combined)];
Should not have an ampersand in front of combined. It should read:
NSData *dataPackage = [NSData dataWithBytes:combined
length: sizeof(combined)];
Third, what matters is sizeof(combined), not sizeof(dataPackage).
The expression sizeof(dataPackage) will tell you the size of the variable dataPackage, which is a pointer to an NSData object. You must be running on a 64 bit device, where pointers are 8 bytes.
To test the length of the data in your NSData object, you want to ask it with the length property:
NSLog(#"sizeof(combined) = %d", sizeof(combined)";
NSData *dataPackage = [NSData dataWithBytes:&combined
length: sizeof(combined)];
NSLog(#"dataPackage.length = %d", dataPackage.length";
Both log statements should display values of 12.

What is UnsafeMutablePointer<Void>? How to modify the underlying memory?

I am trying to work with SpriteKit's SKMutableTexture class but I don't know how to work with UnsafeMutablePointer< Void >. I have a vague idea that it is a pointer to a succession of byte data in memory. But how can I update it? What would this actually look like in code?
Edit
Here is a basic code sample to work with. How would I get this to do something as simple as create a red square on the screen?
let tex = SKMutableTexture(size: CGSize(width: 10, height: 10))
tex.modifyPixelDataWithBlock { (ptr:UnsafeMutablePointer<Void>, n:UInt) -> Void in
/* ??? */
}
From the docs for SKMutableTexture.modifyPixelDataWithBlock:
The texture bytes are assumed to be stored as tightly packed 32 bpp, 8bpc (unsigned integer) RGBA pixel data. The color components you provide should have already been multiplied by the alpha value.
So, while you’re given a void*, the underlying data is in the form of a stream of 4x8 bits.
You could manipulate such a structure like so:
// struct of 4 bytes
struct RGBA {
var r: UInt8
var g: UInt8
var b: UInt8
var a: UInt8
}
let tex = SKMutableTexture(size: CGSize(width: 10, height: 10))
tex.modifyPixelDataWithBlock { voidptr, len in
// convert the void pointer into a pointer to your struct
let rgbaptr = UnsafeMutablePointer<RGBA>(voidptr)
// next, create a collection-like structure from that pointer
// (this second part isn’t necessary but can be nicer to work with)
// note the length you supply to create the buffer is the number of
// RGBA structs, so you need to convert the supplied length accordingly...
let pixels = UnsafeMutableBufferPointer(start: rgbaptr, count: Int(len / sizeof(RGBA))
// now, you can manipulate the pixels buffer like any other mutable collection type
for i in indices(pixels) {
pixels[i].r = 0x00
pixels[i].g = 0xff
pixels[i].b = 0x00
pixels[i].a = 0x20
}
}
UnsafeMutablePointer<Void> is the Swift equivalent of void* - a pointer to anything at all. You can access the underlying memory as its memory property. Typically, if you know what the underlying type is, you'll coerce to a pointer to that type first. You can then use subscripting to reach a particular "slot" in memory.
For example, if the data is really a sequence of UInt8 values, you could say:
let buffer = UnsafeMutablePointer<UInt8>(ptr)
You can now access the individual UIInt8 values as buffer[0], buffer[1], and so forth.

break a 32bit integer, and use the second half 16bit to form an int

I am making an app that downloads a 32bit integer from server, and use the first 16bit and second 16bit for different purposes...
I am responsible for the second 16bit, which should be used to form an int, I know I should use bitwise operation to do this, but unable to achieve, below is the code that I am using, please give me more information.
//CID is a 32bit integer, in nslog it shows as 68913219 - its different for every user
Byte lowByte = (CID>>16)&0xFF; //the 3rd byte
Byte highByte = (CID>>24)&0xFF; //the 4th byte
uint16_t value = lowByte & highByte; //combine, but the result is 0.
uint16_t value = lowByte & highByte; //combine, but the result is 0.
This is not how you combine two bytes into a single uint16_t: you are ANDing them in place, while you need to shift the high byte, and OR it with the low byte:
uint16_t value = lowByte | (((uint16_t)highByte) << 8);
However, this is suboptimal in terms of readability: if you start with a 32-bit integer, and you need to cut out the upper 16 bits, you could simply shift by 16, and mask with 0xFFFF - i.e. the same way that you cut out the third byte, but with a 16-bit mask.
You shouldn't need to do this byte-by-byte. Try this:
//CID is a 32bit integer, in nslog it shows as 68913219 - its different for every user
uint16_t value = (CID>>16)&0xffff;
You can also use NSData.
If you have this integer:
int i = 1;
You can use :
NSData *data = [NSData dataWithBytes: &i length: sizeof(i)];
and then, to get the second 16bit do:
int16_t recover;
[data getBytes: &recover range: NSMakeRange(2, 2)]
Then you have your 16 bits on "recover".
Maybe this way is not so efficient like bit operation, but it is clearer.
:D

Byte array shows value but the ImgView.Image shows null in ios

I am trying to display an image into UIImageView through this method NSData.FromArray() but it gives an null reference exception my code is the following:
Byte _imgData = GetRawData(_imgPath); // this method get the byte array of size ([131072])
NSData _data = NSData.FromArray(_imgData);
ImgView.Image = UIImage.LoadFromData(_data) //in this _data shows the byte array value but the ImgView.Image shows null
Byte array get the RLE Compress data.
ImgView.Image = UIImage.LoadFromData(_data)
_data is RLE compress byte data I don't know how I can convert it to IOS supported image format.
It gives an error, any suggestions to solve this issue?
UIImage.Load* methods will return null if the data (be it a NSData or a filename) is invalid and/or the format is unknown to UIImage.
You'll likely need to use a lower level API to provide some data (e.g. width, height, depth) about any RAW data. Once that's done you can construct an UIImage on top of it.

Resources