使用Lua C函数时减少重复的任何提示

时间:2015-12-01 13:21:49

标签: c lua

我有一段看起来像这样的代码:

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宏?

3 个答案:

答案 0 :(得分:5)

您可以通过替换

将长度减少1/3
lua_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结构)它会很有用位)。