C ++ error: you need to call a link to a non-stationary member function

I am trying to create a class to ignore the basic behavior of the libuv network functions.

#define TCP_BACKLOG 256 class _tcp { uv_tcp_t* tcp = NULL; public: ~_tcp() { delete tcp; } void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) { printf("NEW CONNECTION\n"); } void listen(const char* host, int port) { tcp = new uv_tcp_t(); uv_tcp_init(uv_default_loop(), tcp); sockaddr_in* addr = new sockaddr_in(); uv_ip4_addr(host, port, addr); uv_tcp_bind(tcp, (const sockaddr*)addr, 0); delete addr; uv_listen((uv_stream_t*)tcp, TCP_BACKLOG, listen_uv_listen_uv_connection_cb); } }; 

The problem with the previously shown code is that when I try to compile it, I get the following error:

 error: reference to non-static member function must be called on: uv_listen((uv_stream_t*)tcp, TCP_BACKLOG, listen_uv_listen_uv_connection_cb); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

And he points to listen_uv_listen_uv_connection_cb as the culprit.

Can someone explain to me why this is a mistake, and how can I fix it?

The signatures uv_listen() and uv_connection_cb are declared as follows

 UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); typedef void (*uv_connection_cb)(uv_stream_t* server, int status); 
+5
source share
3 answers

You cannot convert a non-stationary member function to a pointer to a function even with the same signature, because technically a member function has a hidden parameter called this . One solution is to make listen_uv_listen_uv_connection_cb static:

 class _tcp { uv_tcp_t* tcp = NULL; public: ~_tcp() { delete tcp; } static void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) { printf("NEW CONNECTION\n"); } void listen(const char* host, int port) { tcp = new uv_tcp_t(); uv_tcp_init(uv_default_loop(), tcp); sockaddr_in* addr = new sockaddr_in(); uv_ip4_addr(host, port, addr); uv_tcp_bind(tcp, (const sockaddr*)addr, 0); delete addr; uv_listen((uv_stream_t*)tcp, TCP_BACKLOG, &_tcp::listen_uv_listen_uv_connection_cb); } }; 

PS, in order to be able to call a non-static method, you will need a way to get a pointer to your _tcp instance from the parameter "uv_stream_t * stream". I would suggest using the "void * uv_handle_t.data" pointer from this document http://docs.libuv.org/en/latest/handle.html#c.uv_handle_t

 static void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) { _tcp *tcp = static_cast<_tcp *>( stream->data ); tcp->regularMethod(); } 

Of course, you must assign this pointer to uv_handle_t.data when initializing uv_tcp_t * :

 void listen(const char* host, int port) { tcp = new uv_tcp_t(); uv_tcp_init(uv_default_loop(), tcp); tcp->data = this; // do not forget it ... } 

and I would move this initialization code to the constructor.

You will need such a static shell for each callback that you intend to use with this library. With C ++ 11, you can probably use lambda instead.

+8
source

The uv_listen() callback connector expects a static or free (outer class) function.

So you should declare your function as follows

 static void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) { printf("NEW CONNECTION\n"); _tcp* thisStream = static_cast<_tcp*>(stream); } 

Well, static_cast<> really requires your _tcp class _tcp inherit from uv_stream_t

 class _tcp : public uv_stream_t { // ... }; 

To extend to your comment

"Could you explain to me why uv_listen expects a static function? Is this behavior for all parameters of the function pointer?"

There is a difference between class function pointers that must be bound to an instance of the class to call, and simple function pointers that work to define any function.

Why uv_listen() expects a simple pointer to a function is hard to say. Maybe because it's the native C-API (I really don't know that) or for the sake of flexibility.


NOTE: You cannot use underscores for any characters (as in class _tcp )!

+1
source
 void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) { printf("NEW CONNECTION\n"); }; <<<<<remove ; 

There should not be a semicolon at the end of a function definition.

And you have to write a constructor / copy ctr / assign statement for this class.

0
source

Source: https://habr.com/ru/post/1206738/


All Articles