[Q] [NSValue valueWithBytes: objCType:]
[Q] [NSValue valueWithBytes: objCType:]
- Subject: [Q] [NSValue valueWithBytes: objCType:]
- From: JongAm Park <email@hidden>
- Date: Thu, 31 Jul 2008 11:37:51 -0700
How are you doing, all?
I found a interesting one with the NSValue class, and would like to ask
a couple of questions.
First, I would like to put data from a callback function to an global or
a singleton NSArray. The data structure which holds the all the data is :
typedef struct simpleDescription {
int dataType;
int dataKind;
unsigned char uuid;
} simpleDescription;
typedef struct complexType {
uint8_t *data;
int dataSize;
int year;
simpleDescription *dataDesc;
int tag;
} complexType;
So, the data to queue is in complexType. It contains chunk of data of
which is is dataSize. While the length of the data is various, but the
length of dataDesc is fixed. ( It will not point to an array of
simpleDescription, but one simpleDescription instance. )
I also made another structure, which is the same to the complexType - data,
typedef struct complexTypeConveyer
{
int dataSize;
int year;
simpleDescription *dataDesc;
int tag;
} complexTypeConveyer;
It is for converting them using [NSValue valueWithBytes: objCType:] easily.
So, the queuing process is :
- (IBAction)encode:(id)sender
{
// Setup complexType
simpleDescription *dataDesc = (simpleDescription *)malloc( sizeof(
simpleDescription ) );
dataDesc->dataType ='JaPA';
dataDesc->dataKind = 'CUST';
dataDesc->uuid = 0x01;
uint8_t *data = (uint8_t *)malloc( 512 );
memset( data, 0x0E, 512 );
complexType dataSet;
dataSet.data = data;
dataSet.dataSize = 512;
dataSet.year = 1980;
dataSet.dataDesc = dataDesc;
dataSet.tag = 1;
[self printComplexType:&dataSet toView:lefTextView];
// Move to the conveyer
complexTypeConveyer theConveyer;
theConveyer.dataSize = dataSet.dataSize;
theConveyer.year = dataSet.year;
theConveyer.dataDesc = dataSet.dataDesc;
theConveyer.tag = dataSet.tag;
NSValue *aValue = [NSValue valueWithBytes:&theConveyer
objCType:@encode(complexTypeConveyer)];
NSLog( @"aValue retainCount = %d", [aValue retainCount] );
NSData *theDataToConvey = [NSData dataWithBytes:dataSet.data
length:dataSet.dataSize];
NSDictionary *conveyDictionary = [NSDictionary
dictionaryWithObjectsAndKeys:aValue, @"complexTypeConveyer",
theDataToConvey, @"dataToConvey",
nil];
mDataQueue = [NSArray arrayWithObject:conveyDictionary];
NSLog( @"aValue retainCount = %d", [aValue retainCount] );
//bzero( data, 512);
free( data );
//bzero( dataDesc, sizeof( simpleDescription ) );
free( dataDesc );
[self recover];
}
As you can see, it will retrieve the queued data in mDataQueue in its -
recover message.
- (void)recover
{
//////////////////////
// Recover the data
complexTypeConveyer recoveredConveyedType;
NSDictionary *recoveredDictionary = (NSDictionary *)[mDataQueue
objectAtIndex:0];
NSValue *recoveredValue = (NSValue *)[recoveredDictionary
objectForKey:@"complexTypeConveyer"];
NSData *recoveredData = (NSData *)[recoveredDictionary
objectForKey:@"datatoConvey"];
[recoveredValue getValue:&recoveredConveyedType];
uint8_t *recoveredInnerData = (uint8_t *)malloc(
recoveredConveyedType.dataSize );
[recoveredData getBytes:recoveredInnerData
length:recoveredConveyedType.dataSize];
// Now restore the complex type
complexType recoveredType;
recoveredType.data = recoveredInnerData;
recoveredType.dataSize = recoveredConveyedType.dataSize;
recoveredType.year = recoveredConveyedType.year;
recoveredType.dataDesc = recoveredConveyedType.dataDesc;
recoveredType.tag = recoveredConveyedType.tag;
[self printComplexType:&recoveredType toView:rightextView];
free( recoveredType.data );
free( recoveredType.dataDesc );
}
There is a reason I didn't include the "data" in the NSValue using the
valueWithBytes: objCType:. When it retrieves the value from the
mDataQueue, the content doesn't seem to be maintained. Also, the
document is somewhat ambiguous.
"An NSValue object is a simple container for a single C or Objectie-C
data item. It can hold any of the scalar types such as int, float, and
char, as welll as pointers, structures, and object ids. "
-- from "Number and Value Programming Topics for Cocoa"
It sounds like that it only transforms pointers in a structure, not the
target content pointed by the pointers. So, as a test I put the dataDesc
just as a pointer to the structure. ( In the source above, dataDesc is
declared as :
(case 1)
simpleDescription *dataDesc
But I also tried :
(case 2)
simpleDescription dataDesc
And assigned its address to the field of the complexType.
The purpose of case 2 is to see if the retrieved data in the recover
function is invalid, because it is declared statically in the "encode"
action handler. ( I thought it should be invalid. However, somehow it
was maintained. This is one of the question I would like to ask. How it
can be maintained although it is out of the scope? From recover
message's point of view, it is declared in the stack area of other
message! )
There are couple of interesting things, anyway.
1. Whether the dataDesc is statically declared or not, although it is
freed in the end of the "encode" action handler, it is still maintained
and could be accessed from another message, "recover". And with the
Memory browser, I could confirm that the memory content was still there.
Why is it so? Does the NSData or NSArray just retains them?
2. However, when I intentionally bzero it, the content is nullified, and
the recover message sees the content as zeros. So, it is not caches in
the NSArray. It seems to me that it just uses by referencing.
3. Should they be also freed in the recover function although it is done
so in the "encode" action handler?
4. Should the dataDesc also be transformed separately as the data is?
5. for the data, I used dataWithBytes: length: thinking that it will
copy the contents, instead of just referencing the original. However, it
turns out that it just references it. I figured that out by bzeroing the
original, and how it is seen in the recover function.
There is another message, dataWithBytesNoCopy:length:. It made me think
that the dataWithBytes:length copies, while the
dataWithBytesNoCopy:length just references it. The explanation on the
dataWithBytes:length: is :
"The number of bytes to 'copy' from bytes."
But as I described, it doesn't seem to copy.
Can anyone help me?
Thank you.
JongAm Park
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden