24

I'm trapped in a situation of argument passing in libev.

Usually, libev receives packages in a function like *receive_callback*, that's OK, but in practice, we need to dispatch a relative *write_callback* to deal with specific jobs according to the received package. For example:

S_RECV_MSG* pstRecvMsg = (S_RECV_MSG*) recv_buff;
switch(pstRecvMsg->wMsgType) {
    case 1: 
        ev_io_init(w, write_callback1, w->fd, EV_WRITE);
        break;
    case 2:
        ev_io_init(w, write_callback2, w->fd, EV_WRITE);
        break;
    case 3:
        // .......
}

My question is, if the write_callbackX also has to read the specific content in the recv_buff, how can we pass the recv_buff argument to the callbackX? Must we bear the burden and ugliness of global variables here?

user1302372
  • 241
  • 2
  • 5
  • 18
    That is the correct answer, if you want to you can write it up as a real answer and accept it, makes it easier for other people to find the information. – dnaq Jul 03 '12 at 19:11
  • 3
    At least you went back and kept researching rather than waiting around for an answer :) Glad you solved it. – Steve Lazaridis Jan 25 '13 at 16:09
  • 15
    I suggest writing your solution as an answer (and then accept it) instead of editing it in the question – Shahbaz Feb 05 '13 at 18:10

2 Answers2

6

The author answered it himself, but in a comment. Since this shows up as unanswered, I am posting his answer in the "answer" section and closing the loop. Not sure if there is a better way... feel free to fix this.

Question author says:

Sorry, I think I got the answer now, and feel deeply ashamed at my carelessness of reading documentation:

struct my_io{
   ev_io io;
   int otherfd;
   void *somedata;
   struct whatever *mostinteresting;
};
// ...
struct my_io w;
ev_io_init (&w.io, my_cb, fd, EV_READ);

And then we use the my_io like this:

static void my_cb (struct ev_loop *loop, ev_io *w_, int revents)
{
   struct my_io *w = (struct my_io *)w_;
   //...
}
Axel Advento
  • 2,995
  • 3
  • 24
  • 32
lsk
  • 532
  • 4
  • 5
3

Yes it's explained in libev document, and there is another way. Each watcher has a void *data member that you can read or modify, and libev will completely ignore it, so you can pass the argument like this:

w->data = (void *)recv_buff;
...
static void my_cb (struct ev_loop *loop, ev_io *w_, int revents)
{
    S_RECV_MSG *recv_buff = (S_RECV_MSG*)w_->data;
    ...
}

see libev document.

Winter Ma
  • 63
  • 6