While reading the doc in libev I find some C code of which the syntax is quite weird.
static void
stdin_cb (EV_P_ ev_io *w, int revents)
{
puts ("stdin ready");
// for one-shot events, one must manually stop the watcher
// with its corresponding stop function.
ev_io_stop (EV_A_ w);
// this causes all nested ev_run's to stop iterating
ev_break (EV_A_ EVBREAK_ALL);
}
I'm not sure what the EV_P_
is here, could anyone help explain it to me?
I have tried to google the syntax of method signature in C but no good matches.
CodePudding user response:
EV_P_
is a macro which means "an ev loop as a parameter, plus a comma".
EV_A_
is a macro which means "an ev loop as an argument, plus a comma".
They are defined as
#define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */
#define EV_P_ EV_P, /* a loop as first of multiple parameters */
#define EV_A loop /* a loop as sole argument to a function call */
#define EV_A_ EV_A, /* a loop as first of multiple arguments */
or as
# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_
(Some whitespace was removed so it would fit better.)
This means
static void stdin_cb( EV_P_ ev_io *w, int revents ) {
puts( "stdin ready" );
ev_io_stop( EV_A_ w );
ev_break( EV_A_ EVBREAK_ALL );
}
is equivalent to
static void stdin_cb( struct ev_loop *loop, ev_io *w, int revents ) {
puts( "stdin ready" );
ev_io_stop( loop, w );
ev_break( loop, EVBREAK_ALL );
}
or
static void stdin_cb( ev_io *w, int revents ) {
puts( "stdin ready" );
ev_io_stop( w );
ev_break( EVBREAK_ALL );
}
Which set of #define
directives is used is configurable.
If EV_MULTIPLICITY
is set and nonzero, the first set is used. The first set allows multiple ev loops to be used in the same program. (Perhaps in different threads.)
If EV_MULTIPLICITY
is unset or zero, the second set is used. The second is more efficient since it uses global variables instead of passing a structure to every ev-related function. But the program can only have one event loop.
CodePudding user response:
See ev.h:
#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P, /* a loop as first of multiple parameters */
...
#else
# define EV_P void
# define EV_P_
...
#endif
Therefore the line
stdin_cb (EV_P_ ev_io *w, int revents)
expands to
stdin_cb (struct ev_loop *loop, ev_io *w, int revents)
or
stdin_cb (ev_io *w, int revents)
depending on the value of EV_MULTIPLICITY
As pointed out by @Shawn, there is a Macro magic section that explains it:
EV_P, EV_P_
This provides the loop parameter for functions, if one is required ("ev loop parameter"). The EV_P form is used when this is the sole parameter, EV_P_ is used when other parameters are following. Example: // this is how ev_unref is being declared static void ev_unref (EV_P); // this is how you can declare your typical callback static void cb (EV_P_ ev_timer *w, int revents) It declares a parameter loop of type struct ev_loop *, quite suitable for use with EV_A.