简化Lua函数调用C函数

时间:2017-03-07 15:56:12

标签: lua

我是Lua的新手

我有一个注册到Lua的C函数,如下所示:

call(obj, "func", param0, param1)

call()

  • 我们通过C ++中的自定义反射逻辑进行一些复杂的函数调度
  • obj(以及所有参数)都是固定包装类型(类似于boost::any

因此,我们不能使用常规的Lua绑定工具(luabind,luabridge等)进行简单的类成员注册

以下是问题:

我们如何简化Lua调用:

obj.func(param0, param1)

obj:func(param0, param1)

感谢。

1 个答案:

答案 0 :(得分:2)

您必须在您创建的每个obj上设置metatable(假设它是您控制下的userdata并且没有metatable)并覆盖__index metamethod:

local cache = { }

debug.setmetatable(obj, {
    __index = function (obj, k)
        return function (obj, ...) -- or (...) for [non-canonical] .-syntax
            return call(obj, k, ...)
        end

        -- malloc-optimized version --
        local f = cache[k] or function (obj, ...) return call(obj, k, ...) end
        cache[k] = f
        return f
    end,
    __metatable = "whatever",
})

f = obj.func
f(obj, param0, param1) --> call(obj, 'func', param0, param1)

obj:func(param0, param1) --> the same via syntactic sugar

如果obj已经有了metatable,那么必须以类似的方式修改metatable。

同样可以通过C界面完成,因此您可以将obj创建与__index设置相结合。

C方面的更新:

如果创建函数在外部库中,那么除了捕获所有对象外观点(在作为参数传递的表中返回值和值)并且如上所述换行之外,你没有其他选项。

如果创建功能在您的控制之下,您可以看到类似的内容:

ud = lua_newuserdata(L, sizeof(object));
*ud = object;

// this part is missing if objects have no metatable at all
luaL_getmetatable(L, tname); // or 'if (luaL_newmetatable(L, tname)) { ... }'
lua_setmetatable(L, -2);

return 1;

您必须在创建metatable的位置添加__index元方法:

...代码中的某个地方,也许就在*ud = object行...

之后
if (luaL_newmetatable(L, tname)) {
    ... original metatable setup ...

    int res = luaL_loadstring(L,
        "return function (obj, k)\n"
        "    return function (obj, ...)\n"
        "        return call(obj, k, ...)\n"
        "    end\n"
        "end\n");
    assert(res == 0);

    lua_call(L, 0, 1);
    lua_setfield(L, -2, "__index");
}

如果您的userdata根本没有metatable,则必须创建并设置它。

如果你想摆脱全局符号call,那么将它的C实现作为参数传递给luaL_loadstring'ed chunk:

luaL_loadstring(L, "local call = ...\n return function (obj, k)\n" ...);
lua_pushcfunction(L, l_call);
lua_call(L, 1, 1); // instead of (0, 1)

然后call将被本地化为闭包。