spandana
spandana

Reputation: 755

passing functions address to the function pointer in Objective C

I need to pass a address of the function to a function pointer.Below is the code what i'm trying to accomplish it.I'm sure that i'm mistaking somewhere so that i'm getting a runtime exception.How to pass the address of a function to a function pointer.Am i missing something in this code.

RS232Msg.h

typedef RS232Msg* (*tpNewMsg)(void);
typedef struct
{
    int         nMessageId;         
    NSString*   szAsciiName;        
    tpNewMsg    pNewMessageFunc;   
} stRs232Struct;   
@interface RS232Msg : NSObject
{
}
@end

RS232Msg.m

@implementation RS232Msg
-(id)initWithRS232Msg:(int)uMessageId withNewMsg:(tpNewMsg)pNewMsg withAsciiName:(const char*)szAsciiName withData:(void*)pData withSize:(size_t)uDataSize
{
 //stmts;
}
@end

RS232Derived.h

@interface RS232MsgRequestSession : RS232Msg{
}

+(RS232Msg*)NewMsg;  

RS232Derived.m

@implementation RS232MsgRequestSession
+(id)FromMsg:(RS232Msg*)pMsg           
{                                                       
    pMsg = [RS232MsgRequestSession alloc];  
    return pMsg;
}             
-(id)init
{   
    if (self = [super initWithRS232Msg:[RS232MsgRequestSession getID] withNewMsg:[RS232MsgRequestSession NewMsg] withAsciiName:NULL withData:&st withSize:sizeof(st)]) {

    }
    return self;
}
@end

A run time exception happens when i tried to pass the address of the function

withNewMsg:
[RS232MsgRequestSession NewMsg]

to the function pointer pNewMsg() in the initWithRS232Msg method.

Upvotes: 0

Views: 712

Answers (1)

Deepak Danduprolu
Deepak Danduprolu

Reputation: 44633

[RS232MsgRequestSession NewMsg] doesn't get you the address of the method. The expression is evaluated and the result object is passed as the argument. While there is a way to access the implementation of a method directly (read this for details), there might be an easier way to achieve what you want.

Selector based approach

Instead of what you're doing right now, you can consider doing something like this,

- (id) initWithTarget:(id)aTarget action:(SEL)aSelector ... {
    // save these two for later reference.
}

and later,

if ( [target respondsToSelector:theSelector] ) {
    result = [target performSelector:theSelector];
}

This way you can achieve what you want.

Blocks based approach

Truth be told, Blocks are turning out to be the best addition to Objective-C.

Change the typedef to typedef RS232Msg* (^tpNewMsg)(void);

Now the init method would become,

-(id)init
{   
    self = [super initWithR232Msg:[RS232MsgRequestSession getID]
                       withNewMsg:^{
                           return [RS232MsgRequestSession NewMsg];
                       }
                    withAsciiName:NULL
                         withData:&st
                         withSize:sizeof(st)]
    if ( self ) {
        // do stuff
    }
    return self;
}
@end

Upvotes: 1

Related Questions