[Libwebsockets] How to pass a lws_callback_function from a c++ class

Pranjali Chumbhale pranjalic at safeai.ai
Tue Mar 24 22:52:30 CET 2020


Hello Andy,

Following up on this one.

I decided to make my callback function static and use it.
Also,

 >Likewise there are .opaque_user_data, .user and some accessors in many
lws objects with user-code defined lifetime.  Put your c++ "this" in
there.  You're dealing with a C library, it has to be dealt with as C.

I was using this approach.

I do the assignment in the following way:
m_protocols[0].name = "my-protocol-name";
m_protocols[0].callback = callback_ws;
m_protocols[0].per_session_data_size = 0;
m_protocols[0].rx_buffer_size = m_max_data_size;
m_protocols[0].user = this; // user code can access this in callback

// terminator - needed by libwebsocket
m_protocols[1].name = NULL;
m_protocols[1].callback = NULL;
m_protocols[1].per_session_data_size = 0;
m_protocols[1].rx_buffer_size = 0;


I was using gdb to debug:
The value of this is getting assigned to user:

(gdb)* print(m_protocols[0].user)*

$5 = (void *) 0x7fffa13f9dc0

(gdb) *print(this)*

$6 = (my_class_name * const) 0x7fffa13f9dc0

But when I get callback, I see that the user field is 0x0.
>From gdb:

my_class_name::callback_ws (wsi=0x56297b06f678,
reason=LWS_CALLBACK_EVENT_WAIT_CANCELLED, *user=0x0*, in=0x0, len=0)

my_class_name::callback_ws (wsi=0x56297aafe2c0,
reason=LWS_CALLBACK_CLIENT_CONNECTION_ERROR,* user=0x0*,
    in=0x7f60636d46eb, len=17)

Regards,
Pranjali


On Tue, Mar 17, 2020 at 5:58 PM <andy at warmcat.com> wrote:

>
>
> On March 18, 2020 12:35:25 AM UTC, Pranjali Chumbhale <pranjalic at safeai.ai>
> wrote:
> >I do not have the option of using a static method.
>
> Lws is C, the compiler is telling you C code doesn't know how to play c++
> games with magically passing "this" object context when invoking the
> dynamic function ptr.  Static function pointers don't need that and are
> compatible with C.
>
> You "don't have the option" to do what you're doing.  Use a static
> function pointer and explicitly store your dynamic object pointer
> somewhere, where depends on the object scope but there should be
> somewhere.  Eg in lws_protocols in your example
>
>
> https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-protocols-plugins.h#n73-74
>
> Likewise there are .opaque_user_data, .user and some accessors in many lws
> objects with user-code defined lifetime.  Put your c++ "this" in there.
> You're dealing with a C library, it has to be dealt with as C.
>
> >I was trying more of
> >https://isocpp.org/wiki/faq/pointers-to-members#memfnptr-vs-fnptr
>
> It doesn't mention C.  If it did, it'd tell you what Brice (and eg,
> libcurl docs) say.
>
> -Andy
>
> >Regards,
> >Pranjali
> >
> >
> >On Tue, Mar 17, 2020 at 5:31 PM Brice Hamon <brice at ydotm.com> wrote:
> >
> >> Use a static method.
> >>
> >> On Tue, Mar 17, 2020 at 8:25 PM Pranjali Chumbhale
> ><pranjalic at safeai.ai>
> >> wrote:
> >>
> >>> Hello Team,
> >>>
> >>> I am trying to pass  a c++ class member function as a callback to
> >>> protocols.
> >>>
> >>> Here is the relevant piece of code.
> >>>
> >>> This is how my callback function is declared.
> >>> int ns::class_name::callback_ws( struct lws *wsi, enum
> >>> lws_callback_reasons reason,
> >>> void *user, void *in, size_t len);
> >>>
> >>>
> >>> This is how I am using it to pass it to protocols:
> >>> std::function<int(struct lws *wsi, enum lws_callback_reasons reason,
> >void
> >>> *user, void *in, size_t len)> callback_func;
> >>>
> >>> callback_func = std::bind(&ns::class_name::callback_ws,this,
> >>> std::placeholders::_1, std::placeholders::_2,
> >>> std::placeholders::_3, std::placeholders::_4,
> >>> std::placeholders::_5);
> >>>
> >>> m_protocols[0].name = "named_protocol";
> >>> m_protocols[0].callback = callback_func;
> >>> m_protocols[0].per_session_data_size = 0;
> >>> m_protocols[0].rx_buffer_size = m_max_data_size;
> >>>
> >>> // terminator - needed by libwebsocket
> >>> m_protocols[1].name = NULL;
> >>> m_protocols[1].callback = NULL;
> >>> m_protocols[1].per_session_data_size = 0;
> >>> m_protocols[1].rx_buffer_size = 0;
> >>>
> >>> I am getting the following error:
> >>>
> >>> error: cannot convert ‘std::function<int(lws*, lws_callback_reasons,
> >>> void*, void*, long unsigned int)>’ to ‘int (*)(lws*,
> >lws_callback_reasons,
> >>> void*, void*, size_t) {aka int (*)(lws*, lws_callback_reasons,
> >void*,
> >>> void*, long unsigned int)}’ in assignment
> >>>    m_protocols[0].callback  = callback_func;
> >>>                               ^~~~~~~~~~~~~
> >>> I do not understand when the return data type of callback function
> >is
> >>> int, why is it throwing error looking for  int(*).
> >>>
> >>> Regards,
> >>> Pranjali
> >>> _______________________________________________
> >>> Libwebsockets mailing list
> >>> Libwebsockets at ml.libwebsockets.org
> >>> https://libwebsockets.org/mailman/listinfo/libwebsockets
> >>>
> >>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://libwebsockets.org/pipermail/libwebsockets/attachments/20200324/943c895f/attachment.htm>


More information about the Libwebsockets mailing list