I have a macro that works as expected, but I want to make some changes to make it cleaner to use.
#define FuncCreate(func_name, func, ...) \
int func_name(lua_State *ms) { \
func(__VA_ARGS__); \
return 0; \
}
FuncCreate(appEvent, app_event, lua_touserdata(ms, 1), lua_tointeger(ms, 2), lua_tostring(ms, 3));
FuncCreate(GdEvent, gd_event, lua_touserdata(ms, 1), lua_touserdata(ms, 2), lua_tostring(ms, 3), lua_tointeger(ms, 4), lua_tostring(ms, 5));
I want to change the way I use arguments in the macro
I want to make use of key from data types e.g.
FuncCreate(appEvent, app_event, struct, int, const char*);
FuncCreate(GdEvent, gd_event, struct, int, const char*, int, const char*);
How can the macro take for example get the names
struct
pass as argument to func
the lua_touserdata
pass int
as an argument to func
or lua_tointeger
Would it be better to create a variadic function? How can I do this ? Remembering that I want to use the key name of the data types
How can the macro take for example get the names
You can use a _Generic to overload over type. Then you can overload a macro over variable number of arguments to pass each function to proper callback.
#define LUA_TO(x) _Generic((x) \
, int: lua_tointeger \
, const char *: lua_tostring \
, void *: lua_touserdata \
)
#define LUA_TO_FOREACH_1(ms,i,a) LUA_TO(a)(ms,i)
#define LUA_TO_FOREACH_2(ms,i,a,...) LUA_TO_FOREACH_1(ms,i,a) LUA_TO_FOREACH_1(ms,i+1,__VA_ARGS__)
#define LUA_TO_FOREACH_3(ms,i,a,...) LUA_TO_FOREACH_1(ms,i,a) LUA_TO_FOREACH_2(ms,i+1,__VA_ARGS__)
#define LUA_TO_FOREACH_4(ms,i,a,...) LUA_TO_FOREACH_1(ms,i,a) LUA_TO_FOREACH_3(ms,i+1,__VA_ARGS__)
#define LUA_TO_FOREACH_N(_4,_3,_2,_1,N,...) LUA_TO_FOREACH##N
#define LUA_TO_FOREACH(ms,...) LUA_TO_FOREACH_N(__VA_ARGS__,_4,_3,_2,_1,__VA_ARGS__)(ms,1,__VA_ARGS__)
#define FUNCCREATE(func_name, func, ...) \
int func_name(lua_State *ms) { \
func(LUA_TO_FOREACH(ms,__VA_ARGS__)); \
return 0; \
}
FUNCCREATE(appEvent, app_event, int, const char*);
// Results in: int appEvent(lua_State *ms) { app_event(_Generic((int) , int: lua_tointeger , const char *: lua_tostring , void *: lua_touserdata )(ms,1) _Generic((const char*) , int: lua_tointeger , const char *: lua_tostring , void *: lua_touserdata )(ms,1 +1)); return 0; };
Would it be better to create a variadic function?
C programming is statically typed and does not have reflection capability. Using a variadic function would lose the information about types, which seems to be of interest here.
Overall, it would be better not to write such code. In C, you would type everything out, line by line. Writing such macro expansions to generate functions results in really hard to maintain and unreadable code that no one is ever able to fix or change later.