How to pass objective-c function as a callback to C function?

I want to call a c function from objective-c and pass objective-c function as a callback

the problem is this function has a callback as parameter, so I have to pass objective-c function as a call back to c function

  • how to get input from UIAlertView?
  • Average progress of all the NSURLSessionTasks in a NSURLSession
  • NSTableView with Checkbox Cell
  • Objective-C: instance variables out of scope in debugger
  • C++ Debug builds broke in Snow Leopard Xcode
  • Cocoa - go to foreground/background programmatically
  • here is the header of the c function

            struct mg_context *mg_start(const struct mg_callbacks *callbacks,
                            void *user_data,
                            const char **configuration_options);
    

    here is where I try to call it

    - (void)serverstarted
    {
        NSLog(@"server started");
    }
    
    
    - (IBAction)startserver:(id)sender {
       NSLog(@"server should start");
       const char *options[] =
       {
           "document_root", "www",
           "listening_ports", "8080",
            NULL
       };
       mg_start(serverstarted(), NULL, options);
      }
    

    I have tried several ways to do it and searched the web to just get a clue how to do it but with not luck

    here is the library I am incuding in my code

    https://github.com/valenok/mongoose

    2 Solutions Collect From Internet About “How to pass objective-c function as a callback to C function?”

    Your chief problem is the first parameter to mg_start(), which is described in the declaration as const struct mg_callbacks *callbacks. You are trying pass a pointer to a function. (Actually you are trying to pass the result of a call to that function, which is even further from the mark.) That isn’t what it says: it says a pointer to a struct (in particular, an mg_callbacks struct).

    The example code at https://github.com/valenok/mongoose/blob/master/examples/hello.c shows you how to configure this struct. You have to create the struct and put the pointer to the callback function inside it. Then you pass the address of that struct.

    Other problems with your code: your callback function itself is all wrong:

    - (void)serverstarted
    {
        NSLog(@"server started");
    }
    

    What’s wanted here is a C function declared like this: int begin_request_handler(struct mg_connection *conn), that is, it takes as parameter a pointer to an mg_connection struct. Your serverstarted not only doesn’t take that parameter, it isn’t even a C function! It’s an Objective-C method, a totally different animal. Your use of the term “Objective-C function” in your title and your question is misleading; C has functions, Objective-C has methods. No Objective-C is going to be used in the code you’ll be writing here.

    What I suggest you do here is to copy the hello.c example slavishly at first. Then modify the content / names of things slowly and bit by bit to evolve it to your own code. Of course learning C would also help, but you can probably get by just by copying carefully.

    As matt already said, you cannot pass an Objective-C method as callback where a C function
    is expected. Objective-C methods are special functions, in particular the receiver (“self”)
    is implicitly passed as first argument to the function.

    Therefore, to use an Objective-C method as request handler, you need an (intermediate) C function as handler and you have to pass self to that function, using the user_data argument. The C function can then call the Objective-C method:

    // This is the Objective-C request handler method:
    - (int)beginRequest:(struct mg_connection *)conn
    {
        // Your request handler ...
        return 1;
    }
    
    // This is the intermediate C function:
    static int begin_request_handler(struct mg_connection *conn) {
        const struct mg_request_info *request_info = mg_get_request_info(conn);
        // Cast the "user_data" back to an instance pointer of your class:
        YourClass *mySelf = (__bridge YourClass *)request_info->user_data;
        // Call instance method:
        return [mySelf beginRequest:conn];
    }
    
    - (IBAction)startserver:(id)sender
    {
        struct mg_callbacks callbacks;
        memset(&callbacks, 0, sizeof(callbacks));
        callbacks.begin_request = begin_request_handler;
        const char *options[] =
        {
            "document_root", "www",
            "listening_ports", "8080",
            NULL
        };
        // Pass "self" as "user_data" argument:
        mg_start(&callbacks, (__bridge void *)self, options);
    }
    

    Remarks:

    • If you don’t use ARC (automatic reference counting) then you can omit the (__bridge ...)
      casts.
    • You must ensure that the instance of your class (“self”)
      is not deallocated while the server is running. Otherwise the YourClass *mySelf
      would be invalid when the request handler is called.