libev中的这个语法是什么?

huangapple go评论66阅读模式
英文:

what this syntax in libev C language?

问题

在阅读libev文档时,我发现了一些C代码,其中语法相当奇怪。

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);
}

我不太确定这里的 EV_P_ 是什么,有人可以帮忙解释一下吗?

我已经尝试了谷歌搜索C方法签名的语法,但没有找到合适的匹配项。

英文:

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.

答案1

得分: 2

请看 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

因此,这行代码:

stdin_cb (EV_P_ ev_io *w, int revents)

展开为:

stdin_cb (struct ev_loop *loop, ev_io *w, int revents)

或者

stdin_cb (ev_io *w, int revents)

这取决于 EV_MULTIPLICITY 的值。

正如 @Shawn 指出的那样,有一个 宏魔术部分 解释了它:

> EV_P, EV_P_
>
> 这为函数提供了循环参数,如果需要的话("ev loop parameter")。当这是唯一的参数时使用 EV_P 形式,当后面还有其他参数时使用 EV_P_ 形式。示例:
>
> // 这是如何声明 ev_unref 的方式
> static void ev_unref (EV_P);
>
> // 这是你可以声明典型回调的方式
> static void cb (EV_P_ ev_timer *w, int revents)
>
> 它声明了一个类型为 struct ev_loop * 的参数 loop,非常适合与 EV_A 一起使用。

英文:

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.

答案2

得分: -1

EV_P_ 是一个宏,表示“一个作为参数的 ev 循环,加上一个逗号”。

EV_A_ 是一个宏,表示“一个作为参数的 ev 循环,加上一个逗号”。

它们在定义如下:

#define EV_P  struct ev_loop *loop  /* 声明中作为唯一参数的循环 */
#define EV_P_ EV_P,                 /* 作为多个参数中的第一个参数 */
#define EV_A  loop                  /* 函数调用中作为唯一参数的循环 */
#define EV_A_ EV_A,                 /* 作为多个参数中的第一个参数 */

或者如下:

# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_

这意味着:

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 );
}

等同于

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 );
}

或者

static void stdin_cb( ev_io *w, int revents ) {
     puts( "stdin ready" );
     ev_io_stop( w );
     ev_break( EVBREAK_ALL );
}

哪一组 #define 指令被使用是可配置的。

如果设置了并且非零 EV_MULTIPLICITY,则使用第一组。第一组允许在同一程序中使用多个 ev 循环(可能在不同的线程中)。

如果未设置或为零,将使用第二组。第二组更高效,因为它使用全局变量而不是将结构传递给每个与 ev 相关的函数。但是程序只能有一个事件循环。

英文:

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.

huangapple
  • 本文由 发表于 2023年1月9日 14:47:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75053931.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定