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

前端 未结 2 1669
你的背包
你的背包 2021-01-03 09:41

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

相关标签:
2条回答
  • 2021-01-03 09:58

    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.
    0 讨论(0)
  • 2021-01-03 10:24

    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.

    0 讨论(0)
提交回复
热议问题