我有一段看起来像这样的代码:
lua_newtable(L);
lua_pushstring(L, "gid");
lua_pushinteger(L, info[i].codepoint);
lua_settable(L, -3);
lua_pushstring(L, "cl");
lua_pushinteger(L, info[i].cluster);
lua_settable(L, -3);
lua_pushstring(L, "ax");
lua_pushnumber(L, pos[i].x_advance);
lua_settable(L, -3);
lua_pushstring(L, "ay");
lua_pushnumber(L, pos[i].y_advance);
lua_settable(L, -3);
lua_pushstring(L, "dx");
lua_pushnumber(L, pos[i].x_offset);
lua_settable(L, -3);
lua_pushstring(L, "dy");
lua_pushnumber(L, pos[i].y_offset);
lua_settable(L, -3);
lua_pushstring(L, "w");
lua_pushinteger(L, extents.width);
lua_settable(L, -3);
lua_pushstring(L, "h");
lua_pushinteger(L, extents.height);
lua_settable(L, -3);
lua_pushstring(L, "yb");
lua_pushinteger(L, extents.y_bearing);
lua_settable(L, -3);
lua_pushstring(L, "xb");
lua_pushinteger(L, extents.x_bearing);
lua_settable(L, -3);
我正在做的只是在表格中设置几个字段。字段是字符串或数字。请注意代码的重复性。
有没有办法让它更清洁,也许使用C宏?
答案 0 :(得分:5)
您可以通过替换
将长度减少1/3lua_pushstring(L, "cl");
lua_pushinteger(L, info[i].cluster);
lua_settable(L, -3);
通过
lua_pushinteger(L, info[i].cluster);
lua_setfield(L, -2, "cl");
等等。
答案 1 :(得分:3)
可能使用C宏?
使用C11通用宏,它变得更简单:
//your middleware's method
public function handle($request, Closure $next)
{
//get the ID
$id = $request->id
}
然后你可以将它包装在#define lua_push(L, X) _Generic((X), const char*: lua_pushstring, \
float: lua_pushnumber, \
int: lua_pushinteger)(L, X)
:
lua_setfield_generic
以下是您的代码的外观:
#define lua_setfield_generic(L, NAME, X) \
lua_push(L, X); \
lua_setfield(L, -2, NAME);
由于您基本上将数据封送到Lua,因此最好使其更具说明性和基于数据。
想象一下这样的lua_setfield_generic(L, "gid", info[i].codepoint);
lua_setfield_generic(L, "cl", info[i].codepoint);
lua_setfield_generic(L, "ax", pos[i].x_advance);
定义:
struct
通过一些聪明的思考,你可以构建一个结构和一个函数STRUCT(Point)
FIELD(x, float);
FIELD(y, float);
END_STRUCT
(创建一个你需要的名称PointToLuaTable
),它将选择适当类型的lua函数并按顺序调用它们,从字段名称中取名(通过##
获得)。
你可以更进一步。制作您自己的预处理器,使用例如Clang的API用于解析结构定义并生成适当的函数,然后作为第二个构建步骤使用这些文件来构建这些函数。
那就是说 - 为什么你会在C中做到这一点?它不是那种旨在实现这一目标的语言。它缺乏反思和适当的泛型,以使其值得。
答案 2 :(得分:2)
您可以使用C预处理器将C宏应用于元组列表:
#define INFO_FIELDS( _ ) \
_( codepoint, "gid", integer ) \
_( cluster, "cl", integer )
#define POS_FIELDS( _ ) \
_( x_advance, "ax", number ) \
_( y_advance, "ay", number ) \
_( x_offset, "dx", number ) \
_( y_offset, "dy", number )
#define EXTENT_FIELDS( _ ) \
_( width, "w", integer ) \
_( height, "h", integer ) \
_( y_bearing, "yb", integer ) \
_( x_bearing, "xb", integer ) \
#define GEN( _m, _n, _t ) \
(lua_push##_t( L, info[i]._m ), lua_setfield( L, -2, _n ));
INFO_FIELDS( GEN )
#undef GEN
#define GEN( _m, _n, _t ) \
(lua_push##_t( L, pos[i]._m ), lua_setfield( L, -2, _n ));
POS_FIELDS( GEN )
#undef GEN
#define GEN( _m, _n, _t ) \
(lua_push##_t( L, extents._m ), lua_setfield( L, -2, _n ));
EXTENT_FIELDS( GEN )
#undef GEN
我不确定它会在你的情况下得到回报,但是如果你可以多次使用这些列表(例如从堆栈中读取值并将它们分配给struct字段,或者在第一个中定义C结构)它会很有用位)。