Function pointers in Obj-C

Discussion in 'Mac Programming' started by TheLee, Nov 20, 2006.

  1. TheLee macrumors member

    Joined:
    Aug 5, 2006
    #1
    Hi, so how do you pass function pointers via class/instance methods in obj-c?

    It should be possible, right? I mean, IMP is a typedef for a function pointer, so something like
    Code:
    - (void) foo:(IMP)bar;
    is valid.

    So how do you do other types of function pointers? I mean... I guess I could typedef all the function pointer types I want, but that just sounds really ugly.
     
  2. savar macrumors 68000

    savar

    Joined:
    Jun 6, 2003
    Location:
    District of Columbia
    #2
    In Objective-C, those thing-a-ma-jigs are called "selectors", not functions.

    They are dispatched quite differently from C functions, due to the fact that they need to support the dynamic nature of Objective-C. But you can pass these structures as parameters just the same by using the @selector() directive.

    http://www.faqs.org/faqs/computer-lang/Objective-C/faq/
     
  3. TheLee thread starter macrumors member

    Joined:
    Aug 5, 2006
    #3
    I'm well aware of them being selectors.

    The thing is, while other places in my program, I've gladly accepted SEL objects, the method I'm trying to implement merely wants a brief callback function pointer (essentially just returning an integer to ostenibly use to update a status bar). I'm just tryign to have to add a class method or instance method in every object that wants to support the callback, as I would have to make these publically declared whereas I could ostensibly use a statically-linked function.

    IMP, while it can be treated as a selector, is defined as
    Code:
    typedef id (*IMP)(id, SEL, ...)
    with its implicit arguments, so I know at the very least you can pass function pointers to methods by using typedefs... but I also want to avoid the ugliness of having to declare a typedef everytime I want to create a function pointer.
     
  4. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #4
  5. TheLee thread starter macrumors member

    Joined:
    Aug 5, 2006
    #5
    well, after a bit of experimentation, i figured it out.

    In case anyone else wants to know, if you ever feel like passing a function pointer to an objective-c method, a quick example is
    Code:
    @interface Something: Object {
    }
     - (void) foo:(int(*)(void))bar;
    @end
    
    @implementation Something
    - (void) foo:(int(*)(void))bar {
       return (*bar)();
    }
    @end
    
    int someFunc( void ) {
        return 9;
    }
    
    int main ( int argc, char **argv ) {
        Something *object = [[Something alloc] init];
    
        printf( "%i\n", [object foo:&someFunc] );
    
        [object release];
    
        return 0; 
    }
    The key being that the signature for passing a function pointer is
    Code:
    (return_type (*) (argument_list))
    you'd think that this would be documented somewhere...
     
  6. shawnl macrumors newbie

    Joined:
    Sep 16, 2008
    #6
    Great info TheLee,

    Could you help me out with some similar functionality? What I need to do is pass my class a function like you do but instead of passing it into a method where it is automatically called I need to pass it into a property for the class to store until it needs to invoke the method but I am having trouble getting he syntax down.
     
  7. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #7
    Here is C code to store a function pointer:
    Code:
    #include <stdio.h>
    
    void myMethod(int,double);
    
    int main(int argc, char *argv[]) {
      void (*callback)(int,double) = NULL;
      callback = &myMethod;
      callback(1,5.);
    }
    
    void myMethod(int argOne,double argTwo) {
      printf("One is: %d, two is: %e\n",argOne,argTwo);
    } 
    
    If you really wanted to do this, the field in your class would be:
    returntype (*nameOfField)(type1,type2,...);

    I don't know why you would do this unless there were C methods that you had to call that were in a library, and you couldn't reproduce their functionality in a class. Otherwise, you could just store a SEL instead.
    http://developer.apple.com/document.../ObjectiveC/Articles/chapter_9_section_3.html

    If there are numerous functions that might be called, you could wrap each one in a method of a particular class, and store the SEL to the proper method instead of the raw C function pointer.

    -Lee
     
  8. darkwing macrumors 65816

    Joined:
    Jan 6, 2004
    #8
    You don't need to put the & before somefunc. In C, it's implicit if you don't put parenthesis after somefunc to actually call it. I'm assuming the same behavior is true for obj-c which is a strict superset of C.
     
  9. shawnl macrumors newbie

    Joined:
    Sep 16, 2008
    #9
    Here is my situation.. I have one class lets call Class1 and it creates an instance of a second Class (Class2). What I need to do is make a method in Class2 that when invoked actually references a method in Class1. I was going to simply add a reference back to Class1 from Class2 but that means they would have to reference each other's .h files which appears to throw an error.
     
  10. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #10
    You're not going to get a function pointer to an objective-C class or instance method. It may be possible, but it's a bad idea. This thread discusses a workaround to classes having one another as fields, and avoiding the include problem:
    http://forums.macrumors.com/showthread.php?t=561949

    If it's a single method you need to call in the class, you have no need to store the function itself at all, you'd just invoke it. if you need to call different classes based on some condition, it still seems like you could do this with a switch statement, but if you absolutely needed to dynamically deal with functions you should look into using SEL as I linked above.

    -Lee
     
  11. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #11
    An IMP is not a function pointer. Let me explain:

    A SEL is a selector - it can be used to invoke a message, with all the mechanisms that Objective-C uses for Objective-C message lookup.

    An IMP is a selector that has been resolved for one specific Objective-C class. An IMP can therefore be used to invoke that specific message, but only if the object in question belongs to the right class; if it is used with the wrong kind of object, your program will most likely crash.

    A function pointer - well, just check in any of the thousands of books about the C language what a function pointer is.

    If you want to be able to pass any function pointer as an argument, just cast it to
    Code:
    void (*) (void)
    . But when you want to call the function, the caller has to know the correct function type and cast the function pointer accordingly. It is obviously safer to not do this casting but to use just the right function pointers so that the compiler can detect problems.
     
  12. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #12
    I shouldn't have let shawnl get away with this hijacking for this reason... TheLee posted the original question in 11/2006, and probably won't be coming back to read this response.

    -Lee
     

Share This Page