如何在使用Lua C函数时减少重复?
2015-12-1 13:21:49
收藏:0
阅读:79
评论:3
我有一段代码如下:
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 宏来实现?
点赞
用户752976
也许可以使用 C 宏?
更实用
使用 C11 通用宏,它变得更简单:
#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_setfield_generic(L, "gid", info[i].codepoint);
lua_setfield_generic(L, "cl", info[i].codepoint);
lua_setfield_generic(L, "ax", pos[i].x_advance);
不那么实用,但很花里胡哨
由于你基本上是在将数据传递到 Lua 中,所以最好将其更加声明式和基于数据。
想象一下这样的 struct 定义:
STRUCT(Point)
FIELD(x, float);
FIELD(y, float);
END_STRUCT
通过巧妙的思考,你可以通过这个结构和一个函数 PointToLuaTable(为创建名称需要使用 ##)来建立一个结构,该函数将选择适当类型的 lua 函数并依次调用它们,从字段的名称中获取名称(通过 # 获得)。
你甚至可以进一步扩展它。制作自己的预处理器,使用 Clang 的 API 解析你的结构定义并生成适当的函数,然后作为第二个构建步骤使用这些文件来构建那些函数。
话虽这样——为什么你要在 C 中这样做?它不是一个专为此设计的语言。它缺乏反射和适当的泛型,不能使它有价值。
2015-12-01 13:35:13
用户3677376
你可以使用 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
我不确定在你的情况下是否值得,但是如果您可以多次使用这些列表(例如从堆栈中读取值并将其分配给结构字段,或首先定义 C 结构),则这将很有用。
2015-12-01 14:21:46
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
你可以通过将以下代码:
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");来减少其长度的三分之一等等。