I'm trying to implement an ARM/DSP shared memory communication. The ARM side puts a block of data on the shared memory (let'sa name it array[]) and sends the address and the size of the block to the DSP side which just reads them.
On the DSP side,
void * buf //address of block on shared memory
int length //size of block
However when I try to read them what i get is actually:
buf[0] = length
buf[1] = array[1]
buf[2] = array[2]
buf[3] = array[3]
:
:
:
It looks as if the length variable overights the first cell of the array (which is kind of strange) or I am using the void pointer the wrong way.
Any suggestions?
i think, that data structure is:
buf[0] = length
buf[1] = array[0]
buf[2] = array[1]
:
buf[length] = array[lenght-1]
and you must reserve buf for lenght+1
Related
Once I have allocated the array, how do I manually free it? Is pointer arithmetic possible in unsafe mode?
Like in C++:
double *A=new double[1000];
double *p=A;
int i;
for(i=0; i<1000; i++)
{
*p=(double)i;
p++;
}
delete[] A;
Is there any equivalent code in Rust?
Based on your question, I'd recommend reading the Rust Book if you haven't done so already. Idiomatic Rust will almost never involve manually freeing memory.
As for the equivalent to a dynamic array, you want a vector. Unless you're doing something unusual, you should avoid pointer arithmetic in Rust. You can write the above code variously as:
// Pre-allocate space, then fill it.
let mut a = Vec::with_capacity(1000);
for i in 0..1000 {
a.push(i as f64);
}
// Allocate and initialise, then overwrite
let mut a = vec![0.0f64; 1000];
for i in 0..1000 {
a[i] = i as f64;
}
// Construct directly from iterator.
let a: Vec<f64> = (0..1000).map(|n| n as f64).collect();
It is completely possible to allocate a fixed-sized array on the heap:
let a = Box::new([0.0f64; 1000]);
Because of deref coercion, you can still use this as an array:
for i in 0..1000 {
a[i] = i as f64;
}
You can manually free it by doing:
std::mem::drop(a);
drop takes ownership of the array, so this is completely safe. As mentioned in the other answer, it is almost never necessary to do this, the box will be freed automatically when it goes out of scope.
I need to find a way to convert an arbitrary character typed by a user into an ASCII representation to be sent to a network service. My current approach is to create a lookup dictionary and send the corresponding code. After creating this dictionary, I see that it is hard to maintain and determine if it is complete:
__asciiKeycodes[#"F1"] = #(112);
__asciiKeycodes[#"F2"] = #(113);
__asciiKeycodes[#"F3"] = #(114);
//...
__asciiKeycodes[#"a"] = #(97);
__asciiKeycodes[#"b"] = #(98);
__asciiKeycodes[#"c"] = #(99);
Is there a better way to get ASCII character code from an arbitrary key typed by a user (using standard 104 keyboard)?
Objective C has base C primitive data types. There is a little trick you can do. You want to set the keyStroke to a char, and then cast it as an int. The default conversion in c from a char to an int is that char's ascii value. Here's a quick example.
char character= 'a';
NSLog("a = %ld", (int)test);
console output = a = 97
To go the other way around, cast an int as a char;
int asciiValue= (int)97;
NSLog("97 = %c", (char)asciiValue);
console output = 97 = a
Alternatively, you can do a direct conversion within initialization of your int or char and store it in a variable.
char asciiToCharOf97 = (char)97; //Stores 'a' in asciiToCharOf97
int charToAsciiOfA = (int)'a'; //Stores 97 in charToAsciiOfA
This seems to work for most keyboard keys, not sure about function keys and return key.
NSString* input = #"abcdefghijklkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*()_+[]\{}|;':\"\\,./<>?~ ";
for(int i = 0; i<input.length; i ++)
{
NSLog(#"Found (at %i): %i",i , [input characterAtIndex:i]);
}
Use stringWithFormat call and pass the int values.
I have recently started programming in iOS.. I am going through a code snippet that declares the following variables:
int rc = 0X00;
sqlite3_stmt *pStmt = 0X00;
FMStatement *stat = 0X00;
BOOL abc = 0X00;
what does this mean?? I read somewhere that setting 0X00 in a reference variable means setting it to NULL (in C). But what does setting a BOOL type variable and an int type variable to 0X00 mean??
I suggest you read up about the basics of programming languages, specifically, C programing with pointers. Objective-C is a superset of C and follows many similar rules.
But to your question:
The 0x in front of the literal values in the code (0x00) specifies that the value is interpreted as hexadecimal rather than decimal. But 0x00(hex) is the same as 0(dec).
int rc = 0x00; //same as int rc = 0;
int is a primitive type in both Obj-C and C that specifies an integer, effectively you are initializing the variable. In the C language you must initialize variables otherwise they could be pointing at a random piece of memory.
Therefore, examine this code:
int a;
int b = 0;
//a is NOT equal to b!
In C, the variable 'a' has not be initialized and therefore its not typically safe to assume that it will be initialized to 0. Always initialize your variable.
If you did a printf, or an NSLog of the variable 'a' you will see that it prints some huge number and it doesnt make sense (sometimes this is compiler dependent)
The same can be said for a BOOL. Although setting a BOOL to 0 is the same as setting it to false;
BOOL flag = 0; //The same as saying BOOL flag = false;
Now for the final part of your code:
FMStatement *stat = 0X00;
Often in Objective-C if you are dealing with pointers and objects you need to initialise the pointer to point at some memory address. The actual memory address is usually determined by the stack/heap and you don't need to worry about that. But you do need to ensure that the pointer isn't pointing to the wrong location (known as a garbage pointer).
To do this, we simply set our pointer to nil. eg:
FMStatement *stat = nil; //This pointer is now safe. Although memory still hasnt been allocated for it yet
This is usually taken care of for you though when you immediately allocate the memory for an object, therefore in this case you don't need to worry about initializing the pointer to nil:
FMStatement *stat = [[FMStatement alloc]init];
Like I said, I recommend you read about basic C programming, allocations, pointers, datatypes, initialising etc, once you have a grasp of this, then move to Objective-C which then builds ontop of it with Object-Oriented stuff.
Good luck.
0X00 is simply 0 in hexadecimal notation. So,
int rc = 0X00;
is the same as
int rc = 0;
Same for BOOL variables, where 0 is the same as NO. Using 0X00 is odd -- it'd make more sense to use 0 or NO where appropriate, and use nil for the pointers.
I have a fairly complex issue regarding the interpretation of packets in an app that I am making. A host app sends a packet to client apps with the following structure:
[Header of 10 bytes][peerID of selected client of variable byte length][empty byte][peerID of a client of variable byte length][empty byte][int of 4 bytes][peerID of client of variable byte length][empty byte][int of 4 bytes]
Here is a sample packet that is produced under this structure:
434e4c50 00000000 006a3134 31303837 34393634 00313233 38313638 35383900 000003e8 31343130 38373439 36340000 0003e8
Converted it looks like this:
CNLP j1410874964 1238168589 Ë1410874964 Ë
"CNLP j" is the packet header of 10 bytes. "1410874964" is the peerID of the selected client. "1238168589" is the peerID of another client. " Ë" has an int value of 1000. "1410874964" is the peerID of the other client (in this case, the selected client). " Ë" also has an int value of 1000. Basically, in this packet I am communicating 2 things - who the selected client is and the int value associated with each client.
My problem exists on the interpretation side (client side). To interpret this particular type of packet, I use the following method:
+ (NSMutableDictionary *)infoFromData:(NSData *)data atOffset:(size_t) offset
{
size_t count;
NSMutableDictionary *info = [NSMutableDictionary dictionaryWithCapacity:8];
while (offset < [data length])
{
NSString *peerID = [data cnl_stringAtOffset:offset bytesRead:&count];
offset += count;
NSNumber *number = [NSNumber numberWithInteger:[data cnl_int32AtOffset:offset]];
offset += 4;
[info setObject:number forKey:peerID];
}
return info;
}
Typically, each of these packets range between 49 and 51 bytes. "offset" is set in a previous method to reflect the byte number after the packet header plus the empty byte after the selected player (in the case of the above packet, 21). "count" is initialized with a value of 1. In the case of this particular example, length is 51. The following method is passed the above arguments:
- (NSString *)cnl_stringAtOffset:(size_t)offset bytesRead:(size_t *)amount
{
const char *charBytes = (const char *)[self bytes];
NSString *string = [NSString stringWithUTF8String:charBytes + offset];
*amount = strlen(charBytes + offset) + 1;
return string;
}
This method is supposed to read through a variable length string in the packet, set the offset to the byte immediately after the empty byte pad behind the peerID string, and return the string that was read. "amount" is then set to the number of bytes the method read through for the string (this is becomes the new value of count after returning to the first method). "offset" and "count" are then added together to become the new "offset" - where interpretation of the int portion of the packet will begin. The above arguments are passed to the following method:
- (int)cnl_int32AtOffset:(size_t)offset
{
const int *intBytes = (const int *)[self bytes];
return ntohl(intBytes[offset / 4]);
}
This method is intended to return the 32 bit (4 byte) int value read at the current offset value of the packet. I believe that the problem exists in this method when the offset is a number that is not divisible by 4. In this case, the first int value of 1000 was correctly interpreted, and 32 was returned as the offset during the first iteration of the while loop. However, during the second iteration, the int value interpreted was 909377536 (obtained from reading bytes 36340000 in the packet instead of bytes 000003E8) This was likely due to the fact that the offset during this iteration was set to 47 (not divisible by 4). After interpreting the 32 bit int in the category above, 4 is added to the offset in the first method to account for a 4 byte (32 bit int). If my intuition about an offset not divisible by zero is correct, any suggestions to get around this problem are greatly appreciated. I have been looking for a way to solve this problem for quite some time and perhaps fresh eyes may help. Thanks for any help!!!
The unportable version (undefined behaviour for many reasons):
return ntohl(*(const int *)([self bytes]+offset));
A semi-portable version is somewhat trickier, but in C99 it appears that you can assume int32_t is "the usual" two's complement representation (no trap representations, no padding bits), thus:
// The cast is necessary to prevent arithmetic on void* which is nonstandard.
const uint8_t * p = (const uint8_t *)[self bytes]+offset;
// The casts ensure the result type is big enough to hold the shifted value.
// We use uint32_t to prevent UB when shifting into the sign bit.
uint32_t n = ((uint32_t)p[0]<<24) | ((uint32_t)p[1]<<16) | ((uint32_t)p[2]<<8) | ((uint32_t)p[3]);
// Jump through some hoops to prevent UB on "negative" numbers.
// An equivalent to the third expression is -(int32_t)~n-1.
// A good compiler should be able to optimize this into nothing.
return (n <= INT32_MAX) ? (int32_t)n : -(int32_t)(UINT32_MAX-n)-1;
This won't work on architectures without 8-bit bytes, but such architectures probably have different conventions for how things are passed over the network.
A good compiler should be able to optimize this into a single (possibly byte-swapped) load on suitable architectures.
iam getting from c.dot net web service
byte[] data = new byte[] {-33, -96,0, 0, 0,0,0,0};
I want to convert this into long value
I tried this
long result = (long)ByteBuffer.wrap(index).getInt();
I am getting the result as -543162368 wheras actual value is 41183
First off you want to call getLong() instead of getInt() on the buffer.
However, the data you're receiving is little-endian, which means that it starts with the low order byte first. ByteBuffers are constructed as default with big endian order. You need to set the order to LITTLE_ENDIAN to get the correct value out.
ByteBuffer buffer = ByteBuffer.wrap(index)
buffer.order(ByteOrder.LITTLE_ENDIAN);
long result = buffer.getLong();
Since you apparently can't set the byte order or use getLong, you will need to do it like this:
// Reverse array
for (int i = 0; i < 4; ++i)
{
byte temp = data[i];
data[i] = data[8-i];
data[8-i] = temp;
}
// Get two ints and shift the first int into the high order bytes
// of the result.
ByteBuffer buffer = ByteBuffer.wrap(data);
long result = ((long)buffer.getInt()) << 32;
result |= (long)buffer.getInt();
result should now contain the value.