LuaIntf 初探

by

很久很久以前其实也就十来天我想给一个 C++项目(简称 H 吧)加 lua 支持,于是我就去努力地看 lua 文档,想把 lua 那蜜汁栈交互方式。以下讨论的都是 Lua 的 C 语言官方库。

它和 C 是这么交互的 - 例如说让你把东西都塞一个栈上然后调用各种方法给予里面的数据在Lua世界的生命,Lua调用C程序也是,把参数压栈里面,返回的也压栈里面: 因为 Lua 允许多返回值,这可比别的语言还要加 Array Tuple 之类的返回多个值简单多了不是吗。不过这个栈应该是只用来和 C 交互的。

这个太难懂了,肯定要找 helper/binding 库嘛。第一个是 lua-icxx ,它本来设定便是生成动态链接库的,但是我要静态链接啊,所以在这一步也花了不少时间。它有一个好,目前我用过的,例如说这样:

LuaInterpreter L;
constexpr auto script = "Your script here";
LuaFuncRef chunk = L.chunkFromString(script);

if(chunk.isError()) {
  // cannot load script
} else {
  // ok
}

LuaTempResult res = chunk(); // yes like this you can pass arguments if you need.
if(res.isError()) {
  // error running, error is res.getErrMsg()
}

它可以很方便地调用 lua 函数 blabla。不过实在话这个不难搞啊。

另外 lua-icxx 是一个放在 SF 的 SVN repo ,要下载源代码有点绕 hhh

但是要绑定 module 啊 class 啊它就不行了。另外一个 LuaIntf 的库在这方面就友好多了,它不仅帮你封装了返回非基础类型的东西时 userdata 的操作(包括 new 啊 check 啊还有 gc),它还可以很方便地构建一个 class 或者是 module。

就像是给 imgui 的 ImVec2 绑定个吧,

LuaBinding(L)
  .beginClass<ImVec2>("ImVec2")
  .addConstructor(LUA_ARGS(_opt<float>, _opt<float>))
  .addProperty("x",
    [](ImVec2 *self) { return self->x; },
    [](ImVec2 *self, float val) { self->x = val; })
  .addProperty("y",
    [](ImVec2 *self) { return self->y; },
    [](ImVec2 *self, float val) { self->y = val; })
  .endClass();

addConstructor()那个LUA_ARGS似乎省略不了。

在脚本里面就是这样子的了:

local a = ImVec2() -- all default val
a = ImVec(2.3)     -- partial default val
a.x                -- get
a.y = 9.03         -- set

是吧很方便吧2333

对于例如说someStruct* someFunc(anotherClass* param)这样子的话,你就需要给它绑定someStruct anotherClass之后就可以愉快地使用啦(上面 ImVec2 也是个struct哟)。

它绑定重载函数有点儿麻烦,我建议使用 lambda 无痛解决。而且有时候返回bool的函数绑定好像有问题,这时用 lambda wrap 一下就好啦

但是它不自带void*的解决方案,这里我提供一个(记得引入头文件):

namespace LuaIntf {
	template<>
	struct LuaTypeMapping<void*> {
		static void push(lua_State *L, void* ptr) {
			lua_pushinteger(L, (lua_Integer)ptr);
		}
		static void* get(lua_State *L, int index) {
			return (void*)luaL_checkinteger(L, index);
		}
		static void* opt(lua_State *L, int index, void* def) {
			return lua_isnoneornil(L, index) ? def : get(L, index);
		}
	};
}

默认的 lua_integer 其实已经可以存下指针了。

另外 Lua 没有 continue 这种流程控制,例如说

while(foo) {
  if(sth) continue;
  bar
}

这些就应该:

while foo do
  if not sth then
    bar
  end
end

Tweet this
Top


创建一个 issue 以申请评论
Create an issue to apply for commentary


协议/License

本作品 LuaIntf 初探 采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,基于 http://ice1000.org/2018/07/27/luaintf/ 上的作品创作。
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
知识共享许可协议