使用宏创建函数时处理左大括号的最佳方法
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>
}
这与您的要求不完全相同,但已经很接近了。
编辑:由于回复似乎集中在 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>
}
这与您的要求不完全相同,但已经很接近了。