使用宏创建函数时处理左大括号的最佳方法

Best way to handle opening brace when using a macro to create functions

编辑:由于回复似乎集中在 void* 到 typed* 的转换上,我已将示例更改为更具体的内容。

我有一堆函数都遵循相同的模式:

int prefix_name(void *p) {
  my_type *t = (my_type *)p;
  <possibly other common lines>

  <function-specific code>
}

static int mod_name(lua_State *L) {
  lua_pushlightuserdata(L, (void *)&KEY);
  lua_gettable(L, LUA_REGISTRYINDEX);
  typed *t = lua_touserdata(L, -1);

  <function-specific code>
}

为了减少打字和拼写错误,我创建了一个简单的宏:

#define API_FUNCTION(name) static int mod_ ## name(lua_State *L) {\
  lua_pushlightuserdata(L, (void *)&KEY);\
  lua_gettable(L, LUA_REGISTRYINDEX);\
  typed *t = lua_touserdata(L, -1);

所以我可以将每个函数写成

API_FUNCTION(name)
  <function-specific code>
}

这很好用,但是因为左大括号在宏中,这破坏了我的编辑器中的大括号匹配功能。有没有我可以在宏中更改的东西,这样我就可以写

API_FUNCTION(name) {
  <function-specific code>
}

并让事情按预期进行?

一种可能的替代方法是将宏定义为

API_FUNCTION(name, ...) int prefix_ ## name(void *p) {\
  my_type *t = (my_type*)p;\
  <possibly other common lines>
  __VA_ARGS__
}

然后称其为

API_FUNCTION(name,
  <function-specific code>
)

乍一看确实可行,但我不喜欢它的样子,而且它还会使预处理器输出更大。

编辑 2:基于 Orel 的代码,我想这样的东西会起作用,尽管它相当丑陋并且意味着额外的函数调用:

#define API_FUNCTION(name) static int mod_ ## name ## _internal(lua_State *L, typed *t);\
static int mod_ ## name(lua_State *L) {\
  lua_pushlightuserdata(L, (void *)&KEY);\
  lua_gettable(L, LUA_REGISTRYINDEX);\
  typed *t = lua_touserdata(L, -1);\
  return mod_ ## name ## _internal(L,t); \
} \
static int mod_ ## name ## _internal(lua_State *L, typed *t)

根据新需求更新。

创建定义添加一个中间函数来调用带有所有参数的函数,您可以在GENERIC_FIRST_LINES

中添加您需要的内容
#include <stdio.h>
#include <stdlib.h>


typedef struct my_type {
    int foo;
    int bar;
} my_type;

#define GENERIC_FN(name) prefix_##name

#define GENERIC_FIRST_LINES(name)               \
{                                               \
    _prefix_##name(12, t);                      \
}                                               \
int _prefix_##name(int L, my_type *t)

#define GENERIC(name)                                  \
    static int _prefix_##name(int L, my_type *t);      \
    static int GENERIC_FN(name)(my_type *t)            \
    GENERIC_FIRST_LINES(name)

GENERIC(toto) {
       return t->foo;
}

int main(void)
{
    my_type t;
    t.foo = 1;
    t.bar = 2;

    printf("%d \n", prefix_toto((void *) &t));
    return 0;
}

because the opening brace is in the macro, this breaks the brace-matching function in my editor. Is there something I could change in the macro so I could write

API_FUNCTION(name) {
  <function-specific code>
}

and have things work as intended?

不,不完全是这样,因为左大括号需要出现在宏替换文本的两部分之间。它绝对可以是替换文本本身的一部分,正如您已经知道的那样,但是如果您想将它与宏分开表达,那么宏的替换文本要么全部在它之前,要么全部在它之后。

但是,您可以将宏拆分为两个:

#define API_FUNCTION(name) static int mod_ ## name(lua_State *L)

#define API_FUNCTION_DECLARATIONS \
    lua_pushlightuserdata(L, (void *)&KEY);\
    lua_gettable(L, LUA_REGISTRYINDEX);\
    typed *t = lua_touserdata(L, -1)

那你可以写

API_FUNCTION(name) {
    API_FUNCTION_DECLARATIONS;

    <function-specific code>
}

这与您的要求不完全相同,但已经很接近了。