Cast error passing a void function with namespace

730 Views Asked by At

I'm trying to wrap, in a C++ class, a server that I wrote using mongoose (a C library). The problem is that I'm trying to pass the function ev_handler to the mg_create_server(), which create the instance of the server in mongoose. But it gives a casting error I believe:

src/Server.cpp:16:44: error: cannot convert 'Server::ev_handler' from
type 'int (Server::)(mg_connection*, mg_event)' to type 'mg_handler_t
{aka int (*)(mg_connection*, mg_event)}'   server =
mg_create_server(NULL, ev_handler);

I tried to make ev_handler static but it has send_index_page(conn) that has to be inside the wrapper class.

void Server::start() {
        struct mg_server *server;
        int numberOfObjects;
        _application = new Application();
        _application->start();

        // Create and configure the server
        server = mg_create_server(NULL, ev_handler);

//... more code here ...
}

int Server::ev_handler(struct mg_connection *conn, enum mg_event ev) {
                switch (ev) {
                        case MG_AUTH:     return MG_TRUE;
                        case MG_REQUEST:  return send_index_page(conn);
                        default:          return MG_FALSE;
                }
}
2

There are 2 best solutions below

1
On BEST ANSWER

Your problem is that you're passing a C++ member function to parameter that wants a free function pointer.

Mongoose is a C API and all of its callback parameters are C style functions, which in C++ are free (not member) functions.

A member function pointer is different from a free function pointer in that it needs the this , or the object on which the method is being called, in order to be called.

In your case, you are passing a member function pointer on the Server class.

When interacting which C APIs, it's common to pass a void* context object which is then passed to the callback. You then pass a pointer to a free function or a static class method (which has no this and can therefore work with C APIs). When the callback is invoked, you then cast the context object to the correct type and call a member function to get back into the object context. I can't see any such facility in Mongoose. Maybe it's there and I'm just not finding it.

You may want to try the already exising Mongoose C++ which forks the original Mongoose project to work better with C++: https://github.com/Gregwar/mongoose-cpp

0
On

The callback needs to be static, then you should use a static stub to redirect to the class instance.

Storing the instance of your class in server_param attribute of mg_server will allow to get it back in a static stub and forward it to this instance.

This could be achieve like this :

class Server
{
public: 
        void start() { 
             mg_create_server(this, ev_handlerStub); 
        }
        static int ev_handlerStub(struct mg_connection *conn, enum mg_event ev) {
             ((Server*)conn->server_param)->ev_handler(conn, ev);
        }
        int ev_handler(struct mg_connection *conn, enum mg_event ev) {
             // job to do with the class instance
        }
 };

Proceeding like this, allow access to class instance inside its ev_handler method.