Search code examples
c++lambdalibuv

Passing c++ lambda to C functions


I am trying to wrap a C++ layer over libuv, and using lambda for callback functions. However gcc is erroring out.

Here is the minified version:

#include <uv.h>

class Test {

public:
  void on_conn(uv_stream_t *server, int status) {   }
  void test() {
    uv_tcp_t server;
    auto err = uv_listen((uv_stream_t*)&server,
             100,
             [this]  (uv_stream_s *server, int status) -> void {
               this->on_conn(server,status);
             });
  }
};

Test t;

The relevant declarations in libuv are:

#   define UV_EXTERN /* nothing */
struct uv_stream_s { ... };
typedef struct uv_stream_s uv_stream_t;
typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);

The error g++ is giving:

$ g++ --version
g++ (GCC) 6.1.1 20160501
<<--ERROR--{reformatted}-->>
t.cpp:15:7: error: cannot convert 
         ‘Test::test()::<lambda(uv_stream_s*, int)>’ to 
‘uv_connection_cb {aka void (*)(uv_stream_s*, int)}’ 
 for argument ‘3’ to ‘int uv_listen(uv_stream_t*, int, uv_connection_cb)’        
 }));

What exactly is broken here ? Any way to make this work ?

UPDATE:

More fun .. this in body of lambda does something ; first call works, second doesn't.

int cfunc( void cb() );

class Test {
public:
  void d(){}
  void test() {
    cfunc( [=]  () {});
    cfunc( [=]  () { this->d(); });
    //cfunc( [this]  () { });
    //cfunc( [&this]  () { });
  }
};

t.cpp:10:34: error: cannot convert ‘Test::test()::<lambda()>’ to ‘void (*)()’ for argument ‘1’ to ‘int cfunc(void (*)())’
 cfunc( [=]  () { this->d(); });

Solution

  • A capturing lambda cannot be converted to a function pointer, only a non-capturing can:

    //Lambda captures 'this', and so cannot be converted to function pointer
    [this](uv_stream_s *server, int status) -> void {
           this->on_conn(server,status);
        }