setting a c object on to the NSObject-Dictionary

Discussion in 'iOS Programming' started by rbeatajane, Jun 13, 2011.

  1. rbeatajane macrumors newbie

    Joined:
    Mar 11, 2011
    #1
    Hi,

    Code:
    NSMutableData* myData = [[NSMutableData alloc]init];
    for(uint32_t nIndex=0; nIndex < pMsg->st.numDescriptions; ++nIndex)
    {
    int8_t  chTemp[RMH_EVENT_ID_DESCRIPTION_LEN + 1];
    myData = [NSMutableData dataWithBytes:pMsg->st.aDescriptions[nIndex].uEventCode length:sizeof(pMsg->st.aDescriptions[nIndex].uEventCode)]; //warning: passing argument 1 of 'dataWithBytes:length:' makes pointer from integer without a cast
    strncpy(chTemp,pMsg->st.aDescriptions[nIndex].szDescription,RMH_EVENT_ID_DESCRIPTION_LEN);// warning: pointer targets in passing argument 1 of '__builtin___strncpy_chk' differ in signedness
    [cEventmap setObject:myData forKey:chTemp];//warning: passing argument 2 of 'setObject:forKey:' from incompatible pointer type
    
    }


    I'm getting warnings. I could not clear this warnings.What change should i do in my code to eliminate these warnings.
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    The chTemp variable is not an object. It's a C array of int8_t.

    You can only add objects to an NSMutableDictionary. So convert the C array to a suitable object, then add that object.


    When posting code, be sure to show the type of each variable. I had to guess that cEventmap is an NSMutableDictionary.


    I can't really tell you what the other warnings are for, because I can't guess what the types of your struct's fields are. The warnings are generally self-evident. When it says this:
    Code:
    warning: passing argument 1 of 'dataWithBytes:length:' makes pointer from integer without a cast
    
    It's telling you that the first argument makes a pointer from an integer without a type cast. You should be able to figure that out if you know the types of the argument and can look up the method in the NSMutableData class reference doc. The first argument is here, hilited in red:
    Code:
    dataWithBytes:[COLOR="Red"]pMsg->st.aDescriptions[nIndex].uEventCode[/COLOR]
     
  3. rbeatajane thread starter macrumors newbie

    Joined:
    Mar 11, 2011
    #3
    Hi,

    Sorry for not asking the question correctly.

    I have tried up a sample program that has the same behaviour as the above code.I could able to run the program without any warnings or error.
    But i'm not getting the expected output.Its printing me the address ( <e8166a70>)i hope so.

    For all NSObject's inorder to retrieve the data from it we use %@.

    I have did the same.The output i'm expecting is 32

    Code:
    main.m
    --------
    
    #import <Foundation/Foundation.h>
    #import "class.h"
    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    	class* cls = [class new];
    	//NSLog(@"Struct is:%d",cls->s.shot);
    	NSString* szEventDescriptions = [[NSString alloc]init];
    	NSNumber* s = [NSNumber new];
    	NSMutableDictionary* dict = [NSMutableDictionary new];
    	NSMutableData* myData = [NSMutableData new];
    	myData = [NSMutableData dataWithBytes:[NSNumber numberWithShort:cls->s.shot] length:sizeof(cls->s.shot)];
    	[dict setObject:myData forKey:@"1"];
    	szEventDescriptions = [dict objectForKey:@"1"];
    	NSLog(@"%@",szEventDescriptions);
                 //s = [dict objectForKey:@"1"];
    	//NSLog(@"%@",s);
        [pool drain];
        return 0;
    }
    
    class.h
    --------
    
    #import <Foundation/Foundation.h>
    
    struct sh
    {
    	unsigned int shot;	
    };
    
    @interface class : NSObject {
    	@public
    	struct sh s;
    }
    
    -(id)init;
    
    @end
    
    class.m
    -------
    
    #import "class.h"
    
    
    @implementation class
    
    -(id)init
    {
    	if (self = [super init]) {
    		s.shot = 32;
    	}
    	return self;
    }
    
    @end
     
  4. chown33, Jun 13, 2011
    Last edited: Jun 13, 2011

    chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    You should have left this NSLog() uncommented, so we can see what you're expecting to get.

    Code:
    NSString* szEventDescriptions = [[NSString alloc]init];
    
    You're leaking this NSString.

    Code:
    NSNumber* s = [NSNumber new];
    
    You're leaking this NSNumber.

    Code:
    NSMutableDictionary* dict = [NSMutableDictionary new];
    NSMutableData* myData = [NSMutableData new];
    
    You're leaking both of these objects.


    Code:
    myData = [NSMutableData dataWithBytes:[NSNumber numberWithShort:cls->s.shot] length:sizeof(cls->s.shot)];
    
    This is nonsense. You seem to be expecting that an NSNumber* is simply a pointer to a struct. This expectation is wrong.

    The NSNumber* returned by this code:
    Code:
    [NSNumber numberWithShort:cls->s.shot]
    is an Objective-C object. It is not simply a pointer to a struct. It's not a pointer to a short, either. Nor a pointer to an int.

    Any time the -> operator is used with an object, it refers to an instance variable. An instance variable, however, is not a struct member. It's an instance variable. The compiler knows the difference, and the two things are not interchangeable.

    So the expression cls->s.shot yields an unsigned int 32 by dereferencing an instance variable. That value (32) is then used to make an NSNumber*. That part is correct. The error lies in thinking that the NSNumber* is a plain pointer to an int, or to a short, or to any other non-opaque data type. It's none of those things. It's a pointer to an opaque object.

    So given the NSNumber*, which is not a simple pointer to a struct, the following is meaningless:
    Code:
    [NSMutableData dataWithBytes:[NSNumber numberWithShort:cls->s.shot] length:sizeof(cls->s.shot)];
    What this does is take some number of bytes from the NSNumber*, and stuff them into an NSMutableData object. The number of bytes is the sizeof an unsigned int (4). The actual bytes, however, are whatever the first 4 bytes of the NSNumber object are. Those bytes ARE NOT the s.shot value (32). The bytes are something internal to the object, as defined by the Objective-C runtime's requirements for what constitutes an object.

    My guess is that you're expecting Objective-C to be like C++. It's not. You need to learn Objective-C on its own terms, as the language it actually is, not some preconceived idea that an object is just like a C or C++ struct.

    Code:
    [dict setObject:myData forKey:@"1"];
    
    Nothing wrong here.

    Code:
    szEventDescriptions = [dict objectForKey:@"1"];
    
    This is wrong. The declared type for szEventDescriptions is NSString* (see above). The actual object that was just stored into the dictionary, however, is not an NSString*, but an NSMutableData*.

    Code:
    NSLog(@"%@",szEventDescriptions);
    
    The %@ format specifier uses the -description method of the object to return an NSString*. For an NSData object, the -description method returns the hex bytes of data between <>'s.


    To summarize, what you've effectively done is store 4 bytes of unpredictable data into an NSMutableData object, then printed its -description string.

    The reason the 4 bytes are unpredictable is because you're using an NSNumber* as if it were a plain ordinary struct pointer, when in fact it's an object pointer. So you're getting the first 4 bytes of an object, which is an internal value, not a pointer to an instance variable.


    What book or online tutorial are you learning Objective-C from?

    What is your programming background? Do you already know plain C? Do you know C++?


    You should probably start with this:
    http://developer.apple.com/library/.../ObjectiveC/Introduction/introObjectiveC.html

    For all the places where you're leaking objects, you'll need this:
    http://developer.apple.com/library/...timeGuide/Articles/ocrtHowMessagingWorks.html

    I recommend that you skip the low-level stuff for now, and simply learn the fundamentals of the language. Until you get that right, and stop expecting it to be just like C structs, I think the low-level stuff will be more a hindrance than a help.
     
  5. rbeatajane thread starter macrumors newbie

    Joined:
    Mar 11, 2011
    #5
    Hi,

    Thanks for explaining me about the mistakes clearly.

    I am new to objective c. I know c and c++ basics and not an expert.

    The comments you gave about the mistakes which i made helped me to understand my mistakes clearly.

    I have corrected my code .Now its working without any memory leak and its printing me the correct output as expected.

    Thanks for explaining me in detail.

    Code:
    #import <Foundation/Foundation.h>
    #import "class.h"
    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    	class* cls = [[class new]autorelease];
    	//NSLog(@"Struct is:%d",cls->s.shot);
    	NSMutableDictionary* dict = [[NSMutableDictionary new]autorelease];
    	[dict setObject:[NSNumber numberWithShort:cls->s.shot] forKey:@"1"];
        NSNumber* s = [dict objectForKey:@"1"];
    	NSLog(@"%@",s);
        [pool drain];
        return 0;
    }
     

Share This Page